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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
// Copyright (C) 2020-2023 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef VC_TESTS_METAHELPERS_H_
#define VC_TESTS_METAHELPERS_H_
#include <functional>
#include <type_traits>
#include <utility>
namespace vir
{
namespace test
{
template <class A, class B, class Op>
constexpr bool
operator_is_substitution_failure_impl(float)
{ return true; }
template <class A, class B, class Op>
constexpr typename std::conditional<true, bool, decltype(
Op()(std::declval<A>(), std::declval<B>()))>::type
operator_is_substitution_failure_impl(int)
{ return false; }
template <class... Ts>
constexpr bool
operator_is_substitution_failure()
{ return operator_is_substitution_failure_impl<Ts...>(int()); }
template <class... Args, class F>
constexpr auto
sfinae_is_callable_impl(int, F &&f) -> typename std::conditional<
true, std::true_type,
decltype(std::forward<F>(f)(std::declval<Args>()...))>::type;
template <class... Args, class F>
constexpr std::false_type
sfinae_is_callable_impl(float, const F &);
template <class... Args, class F>
constexpr bool
sfinae_is_callable(F &&)
{
return decltype(
sfinae_is_callable_impl<Args...>(int(), std::declval<F>()))::value;
}
template <class... Args, class F>
constexpr auto sfinae_is_callable_t(F &&f)
-> decltype(sfinae_is_callable_impl<Args...>(int(), std::declval<F>()));
template <class A, class B>
constexpr bool
has_less_bits()
{ return std::__digits_v<A> < std::__digits_v<B>; }
} // namespace test
} // namespace vir
struct assignment
{
template <class A, class B>
constexpr decltype(std::declval<A>() = std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) = std::forward<B>(b)))
{ return std::forward<A>(a) = std::forward<B>(b); }
};
struct bit_shift_left
{
template <class A, class B>
constexpr decltype(std::declval<A>() << std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) << std::forward<B>(b)))
{ return std::forward<A>(a) << std::forward<B>(b); }
};
struct bit_shift_right
{
template <class A, class B>
constexpr decltype(std::declval<A>() >> std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) >> std::forward<B>(b)))
{ return std::forward<A>(a) >> std::forward<B>(b); }
};
struct assign_modulus
{
template <class A, class B>
constexpr decltype(std::declval<A>() %= std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) %= std::forward<B>(b)))
{ return std::forward<A>(a) %= std::forward<B>(b); }
};
struct assign_bit_and
{
template <class A, class B>
constexpr decltype(std::declval<A>() &= std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) &= std::forward<B>(b)))
{ return std::forward<A>(a) &= std::forward<B>(b); }
};
struct assign_bit_or
{
template <class A, class B>
constexpr decltype(std::declval<A>() |= std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) |= std::forward<B>(b)))
{ return std::forward<A>(a) |= std::forward<B>(b); }
};
struct assign_bit_xor
{
template <class A, class B>
constexpr decltype(std::declval<A>() ^= std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) ^= std::forward<B>(b)))
{ return std::forward<A>(a) ^= std::forward<B>(b); }
};
struct assign_bit_shift_left
{
template <class A, class B>
constexpr decltype(std::declval<A>() <<= std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) <<= std::forward<B>(b)))
{ return std::forward<A>(a) <<= std::forward<B>(b); }
};
struct assign_bit_shift_right
{
template <class A, class B>
constexpr decltype(std::declval<A>() >>= std::declval<B>())
operator()(A &&a, B &&b) const noexcept(noexcept(
std::forward<A>(a) >>= std::forward<B>(b)))
{ return std::forward<A>(a) >>= std::forward<B>(b); }
};
template <class A, class B, class Op = std::plus<>>
constexpr bool is_substitution_failure
= vir::test::operator_is_substitution_failure<A, B, Op>();
using vir::test::sfinae_is_callable;
using vir::test::has_less_bits;
#endif // VC_TESTS_METAHELPERS_H_
|