-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path211215_perfect_forwarding.cpp
More file actions
102 lines (80 loc) · 2.33 KB
/
211215_perfect_forwarding.cpp
File metadata and controls
102 lines (80 loc) · 2.33 KB
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
// CLASS TEMPLATE integral_constant
template <typename T, T val>
struct integral_constant
{
using value_type = T;
using type = integral_constant<T, val>;
static constexpr T value = val;
constexpr operator value_type() const noexcept { return value; }
constexpr value_type operator()() const noexcept { return value; }
};
// ALIAS_TEMPLATE bool_constant
template <bool B>
using bool_constant = integral_constant<bool, B>;
// TYPE ALIAS
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
static_assert(true_type::value);
static_assert(not false_type::value);
static_assert(true_type());
static_assert(bool(true_type()));
static_assert(true_type()());
template <typename T>
struct type_identity { using type = T; };
// CLASS TEMPLATE remove_reference
// primary template
template <typename T>
struct remove_reference : type_identity<T> {};
// partial specialization
template <typename T>
struct remove_reference<T&> : type_identity<T> {};
// partial specialization
template <typename T>
struct remove_reference<T&&> : type_identity<T> {};
// ALIAS TEMPLATE remove_reference_t
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
// CLASS TEMPLATE is_same
// primary template
template <typename, typename>
struct is_same : false_type {};
// partial specialization
template <typename T>
struct is_same<T, T> : true_type {};
// VARIABLE TEMPLATE is_same_v
template <typename T, typename S>
inline constexpr bool is_same_v = is_same<T, S>::value;
static_assert(is_same_v<int, int>);
static_assert(not is_same_v<int, int&>);
static_assert(not is_same_v<int, int&&>);
static_assert(not is_same_v<int&, int&&>);
static_assert(not is_same_v<int const, int>);
static_assert(not is_same_v<int const&, int&>);
// move
template <typename T>
remove_reference_t<T>&& move(T&& arg)
{
return static_cast<remove_reference_t<T>&&>(arg);
}
// forward
template <typename T>
T&& forward(remove_reference_t<T>& arg)
{
return static_cast<T&&>(arg);
}
template <typename T>
void test1(T&& arg)
{
static_assert(is_same_v<int&&, decltype(forward<T>(arg))>);
}
template <typename T>
void test2(T&& arg)
{
static_assert(is_same_v<int&, decltype(forward<T>(arg))>);
}
int main()
{
test1(42); // static_assert error if test2(42)
int a = 42;
test2(a); // static_assert error if test1(a)
}