src/generics/oneof.h

changeset 1428
ece049033adc
equal deleted inserted replaced
1427:b7ba2af33c13 1428:ece049033adc
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, &parameters[0], &parameters[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");

mercurial