siplasplas
A library for C++ reflection and introspection
staticif.hpp
1 #ifndef SIPLASPLAS_UTILITY_STATICIF_HPP
2 #define SIPLASPLAS_UTILITY_STATICIF_HPP
3 
4 #include "meta.hpp"
5 #include "identity.hpp"
6 #include <utility>
7 
8 namespace cpp
9 {
10 
11 namespace detail
12 {
13 
32 template<bool Condition>
33 class If
34 {
35 public:
36  template<typename T>
37  class ElseBypass
38  {
39  public:
40  constexpr ElseBypass(T&& value) :
41  _value{std::move(value)}
42  {}
43 
44  template<typename Body>
45  constexpr T Else(const Body&)
46  {
47  return std::move(_value);
48  }
49 
50  private:
51  T _value;
52  };
53 
54  template<typename T>
55  class ElseBypass<T&>
56  {
57  public:
58  constexpr ElseBypass(T& value) :
59  _value{&value}
60  {}
61 
62  template<typename Body>
63  constexpr T& Else(const Body&)
64  {
65  return static_cast<T&>(*this);
66  }
67 
68  constexpr operator T&()
69  {
70  return *_value;
71  }
72 
73  T& operator()()
74  {
75  return *_value;
76  }
77 
78  private:
79  T* _value;
80  };
81 
82  template<typename Body, typename... Args>
83  constexpr auto Then(const Body& body, Args&&... args) ->
84  typename std::enable_if<
85  !std::is_void<decltype(body(::cpp::Identity(), std::forward<Args>(args)...))>::value,
86  ElseBypass<decltype(body(::cpp::Identity(), std::forward<Args>(args)...))>
87  >::type
88  {
89  return body(::cpp::Identity(), std::forward<Args>(args)...);
90  }
91 
92  template<typename Body, typename... Args>
93  constexpr auto Then(const Body& body, Args&&... args) ->
94  typename std::enable_if<
95  std::is_void<decltype(body(::cpp::Identity(), std::forward<Args>(args)...))>::value,
96  If&
97  >::type
98  {
99  body(::cpp::Identity(), std::forward<Args>(args)...);
100  return *this;
101  }
102 
103 
104  template<typename Body, typename... Args>
105  constexpr void Else(const Body&, Args&&...)
106  {
107  /* NOTHING */
108  }
109 };
110 
111 template<>
112 class If<false>
113 {
114 public:
115  constexpr If() = default;
116 
117  template<typename Body, typename... Args>
118  constexpr If& Then(const Body&, Args&&...)
119  {
120  return *this;
121  }
122 
123  template<typename Body, typename... Args>
124  constexpr decltype(auto) Else(const Body& body, Args&&... args)
125  {
126  return body(Identity(), std::forward<Args>(args)...);
127  }
128 };
129 
130 }
131 
244 template<bool Condition, typename ThenBody, typename... Args>
245 auto staticIf(const ThenBody& thenBody, Args&&... args)
246 {
248  return if_.Then(thenBody, std::forward<Args>(args)...);
249 }
250 
251 }
252 
253 #endif // SIPLASPLAS_UTILITY_STATICIF_HPP
A functor class implementing the identity function.
Definition: identity.hpp:21
Definition: canary_allocator.hpp:7
auto staticIf(const ThenBody &thenBody, Args &&...args)
Implements an static conditional.
Definition: staticif.hpp:245
Implements the then branch of an static conditional.
Definition: staticif.hpp:33