|
1 #pragma once |
|
2 #include <array> |
|
3 |
|
4 namespace detail |
|
5 { |
|
6 template<typename T, typename Vt> |
|
7 constexpr bool oneOfCompare(const T& value, Vt *first, Vt *last) |
|
8 { |
|
9 return (first == last) |
|
10 ? false |
|
11 : (*first) == value |
|
12 ? true |
|
13 : detail::oneOfCompare(value, first + 1, last); |
|
14 } |
|
15 |
|
16 template<typename Vt, std::size_t N> |
|
17 struct OneOfClass |
|
18 { |
|
19 std::array<Vt, N> parameters; |
|
20 |
|
21 template<typename... Ts> |
|
22 constexpr OneOfClass(Ts&&... parameters) : |
|
23 parameters {{parameters...}} {} |
|
24 |
|
25 template<typename T> |
|
26 constexpr bool operator==(const T& value) const |
|
27 { |
|
28 return detail::oneOfCompare(value, ¶meters[0], ¶meters[N]); |
|
29 } |
|
30 |
|
31 template<typename T> |
|
32 constexpr bool operator!=(const T& value) const |
|
33 { |
|
34 return !(*this == value); |
|
35 } |
|
36 |
|
37 template<typename T> |
|
38 constexpr friend bool operator==(const T& value, const OneOfClass<Vt, N>& array) |
|
39 { |
|
40 return array == value; |
|
41 } |
|
42 |
|
43 template<typename T> |
|
44 constexpr friend bool operator!=(const T& value, const OneOfClass<Vt, N>& array) |
|
45 { |
|
46 return array != value; |
|
47 } |
|
48 }; |
|
49 }; |
|
50 |
|
51 /* |
|
52 * Returns such an object that compares equal to some value if and only if any of the parameters do. |
|
53 * Example: (x == any(1, 2, 3)) is equivalent to (x == 1 || x == 2 || x == 3) other than the lack of lazy-evaluation |
|
54 */ |
|
55 template<typename... Ts> |
|
56 constexpr auto oneOf(Ts&&... parameters) |
|
57 { |
|
58 using Vt = typename std::common_type<Ts...>::type; |
|
59 return detail::OneOfClass<Vt, sizeof...(Ts)>({parameters...}); |
|
60 } |
|
61 |
|
62 static_assert(oneOf(1,2,3) == 3, "oneOf unit test"); |
|
63 static_assert(oneOf(1,2,3) != 5, "oneOf unit test"); |
|
64 static_assert(3 == oneOf(1,2,3), "oneOf unit test"); |
|
65 static_assert(5 != oneOf(1,2,3), "oneOf unit test"); |