TCPSPSuite
template_magic.hpp
1 //
2 // Created by lukas on 10.04.18.
3 //
4 
5 #ifndef TCPSPSUITE_TEMPLATE_MAGIC_HPP
6 #define TCPSPSUITE_TEMPLATE_MAGIC_HPP
7 
8 #include <type_traits>
9 
10 namespace utilities {
11 
12 /*
13  * Allows your classes to optionally contain members, without re-writing the
14  * whole class in a partial specialization.
15  */
16 template<class T, bool enabled>
17 struct OptionalMember {} ;
18 
19 template<class T>
20 struct OptionalMember<T, false> {
21  /* Accept anything inside the constructor */
22  template<class ... Ts>
23  OptionalMember(Ts ...) {}
24 };
25 
26 template<class T>
27 struct OptionalMember<T, true> : public T
28 {
29 public:
30  using T::T;
31 };
32 
33  /*
34  * Allows switching of member types based on a constexpr
35  * bool expression.
36  */
37  template<class TrueType, class FalseType, bool b>
38  struct ConditionalMember {};
39 
40  template<class TrueType, class FalseType>
41  struct ConditionalMember<TrueType, FalseType, true> : public TrueType
42  {
43  public:
44  using TrueType::TrueType;
45  };
46 
47  template<class TrueType, class FalseType>
48  struct ConditionalMember<TrueType, FalseType, false> : public FalseType
49  {
50  public:
51  using FalseType::FalseType;
52  };
53 
54 
55 /*
56  * This is inspired by
57  *
58  * https://stackoverflow.com/questions/34099597/check-if-a-type-is-passed-in-variadic-template-parameter-pack
59  *
60  * and should be converted to std::disjunction as soon as C++17 becomes available on reasonable
61  * compilers.
62  */
63 template<typename QueryT>
64 constexpr bool pack_contains() {
65  return false;
66 }
67 
68 // Forward
69 template<typename QueryT, typename First, typename ...Rest>
70 constexpr bool pack_contains();
71 
72 template<typename QueryT, bool found, typename ...Rest>
73 constexpr typename std::enable_if<found, bool>::type pack_contains_forward() {
74  return true;
75 }
76 
77 template<typename QueryT, bool found, typename ...Rest>
78 constexpr typename std::enable_if<! found, bool>::type pack_contains_forward() {
79  return pack_contains<QueryT, Rest...>();
80 }
81 
82 template<typename QueryT, typename First, typename ...Rest>
83 constexpr bool pack_contains() {
84  return pack_contains_forward<QueryT, std::is_same<QueryT, First>::value, Rest...>();
85 }
86 
87 /*
88  * Merges two parameter Packs
89  */
90 
91 
92 /*
93  * Generic class to contain a template parameter pack
94  */
95 template<class ...> struct pack {};
96 
97 }
98 
99 #endif //TCPSPSUITE_TEMPLATE_MAGIC_HPP