-
Notifications
You must be signed in to change notification settings - Fork 0
/
concept.cpp
130 lines (108 loc) · 2.44 KB
/
concept.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <concepts>
// ways of doing concepts in cpp 20+
template <typename T>
void print_number1(T n)
{
static_assert(std::is_integral<T>::value, "Must pass in an integral argument");
std::cout << "n: " << n << std::endl;
}
template <typename T>
requires std::integral<T>
T add_number1(T a, T b)
{
return a + b;
}
template <typename T>
requires std::is_integral_v<T>
T add_number2(T a, T b)
{
return a + b;
}
template<std::integral T>
T add_number3(T a, T b)
{
return a + b;
}
auto add_number4(std::integral auto a, std::integral auto b)
{
return a + b;
}
template <typename T>
T add_number5(T a, T b) requires std::integral<T>
{
return a + b;
}
// custom concept
template <typename T>
concept MyIntegral = std::is_integral_v<T>;
template <typename T>
concept Multipliable = requires (T a, T b)
{
a * b; // makes sure the syntax is valid
};
template <typename T>
concept Incrementable = requires (T a)
{
a += 1;
++a;
a++;
};
template <typename T>
requires MyIntegral<T>
T add_number6(T a, T b)
{
return a + b;
}
template <MyIntegral T>
T add_number7(T a, T b)
{
return a + b;
}
auto add_number8(MyIntegral auto a, MyIntegral auto b)
{
return a + b;
}
// check the size in concept
template <typename T>
concept TinyType = requires(T a, T b)
{
sizeof(T) <= 4; // always True because cencept is checking sytanx
requires sizeof(T) <= 4; // nested requirement
{a + b} noexcept -> std::convertible_to<int>; // compond requirement
};
template <typename T>
T add_number9(T a, T b) requires std::integral<T> || std::floating_point<T>
{
return a + b;
}
template <typename T>
T add_number10(T a, T b) requires std::floating_point<T> && requires (T t) {sizeof(T) <= 4; requires sizeof(T) <= 4;}
{
return a + b;
}
// template override - does not work :'(
// template <>
// requires std::floating_point<T>
// double add_number2(double x, double y)
// {
// return x + y;
// }
std::integral auto add(std::integral auto x, std::integral auto y)
{
return x + y;
}
int main()
{
std::integral auto x = add(10, 20);
std::floating_point auto y = 7.7;
// print_number1(30.2);
// std::cout << add_number1(1.0, 4.2) << std::endl;
// std::cout << add_number2(1.0, 4.2) << std::endl;
// std::cout << add_number3(1.0, 4.2) << std::endl;
// std::cout << add_number4(1.0, 4.2) << std::endl;
// std::cout << add_number5(1.0, 4.2) << std::endl;
// std::cout << add_number9(1, 4) << std::endl;
// std::cout << add_number10(2.0, 4.2) << std::endl;
return 0;
}