-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathswitch.h
More file actions
108 lines (93 loc) · 2.4 KB
/
switch.h
File metadata and controls
108 lines (93 loc) · 2.4 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
103
104
105
106
107
108
//
// switch.h
// switch
//
// Created by Sandy Martel on 5/1/17.
// Copyright © 2017 sandy. All rights reserved.
//
#ifndef H_CPP_SWITCHER
#define H_CPP_SWITCHER
#include <type_traits>
#include <tuple>
#include <utility>
#include <ciso646>
namespace Switcher_details
{
template<typename LHS, typename RHS>
struct value_equal_impl
{
inline bool operator()( const LHS &lhs, const RHS &rhs ) { return lhs == rhs; }
};
// specialisation for matches marked as 'ignore'
template<typename RHS>
struct value_equal_impl<std::decay<decltype(std::ignore)>::type,RHS>
{
inline bool operator()( const std::decay<decltype(std::ignore)>::type &lhs, const RHS &rhs ) { return true; }
};
// helper function
template<typename LHS, typename RHS>
inline bool value_equal( const LHS &lhs, const RHS &rhs )
{
return value_equal_impl<LHS,RHS>()( lhs, rhs );
}
template <size_t I>
struct tuple_equal
{
template <typename LHS, typename RHS>
inline bool operator()( const LHS &lhs, const RHS &rhs )
{
return tuple_equal<I-1>()( lhs, rhs) and value_equal( std::get<I-1>(lhs), std::get<I-1>(rhs) );
}
};
template <>
struct tuple_equal<0>
{
template <typename LHS, typename RHS>
inline bool operator()( const LHS &lhs, const RHS &rhs ) { return true; }
};
}
template<typename ...VALUES>
class Switcher
{
private:
std::tuple<VALUES...> values;
bool matched = false;
template <class T, std::size_t... I>
constexpr auto extract_matches( T &&t, std::index_sequence<I...>) const
{
return std::forward_as_tuple( std::get<I>( std::forward<T>(t))... );
}
public:
Switcher( VALUES ...v ) : values( v... ){}
template<typename ...MATCHES_AND_FUNC>
Switcher &Case( MATCHES_AND_FUNC ...t )
{
static_assert( (sizeof...(MATCHES_AND_FUNC)-1) == sizeof...(VALUES), "" );
if ( not matched )
{
auto matches_and_func = std::make_tuple( t... );
auto matches = extract_matches(
std::forward<std::tuple<MATCHES_AND_FUNC...>>( matches_and_func ),
std::make_index_sequence<sizeof...(VALUES)>{} );
if ( Switcher_details::tuple_equal<sizeof...(VALUES)>()( matches, values ) )
{
// marked as done and call the function
matched = true;
std::get<sizeof...(VALUES)>( matches_and_func )();
}
}
return *this;
}
template<typename FUNC>
void Default( const FUNC &i_func )
{
if ( not matched )
i_func();
}
};
template<typename ...T>
Switcher<T...> Switch( T ...t )
{
return Switcher<T...>( t... );
}
#endif