Scarab  v3.5.3
Project 8 C++ Utility Library
unique_typelist.hh
Go to the documentation of this file.
1 /*
2  * unique_typelist.hh
3  *
4  * Created on: Oct 3, 2018
5  * Author: N.S. Oblath
6  *
7  * This file allows you to create type lists with unique elements.
8  *
9  * The typelist itself is a standard type list, and the uniqueness of the elements is
10  * enforced as elements are appended using `unique_append`.
11  *
12  * Test code is commented out below as an example of how to use the append functionality.
13  *
14  * The current version works for types; a version that made integer lists was explored but a problem was found
15  * that didn't have an obvious work-around. That path was abandoned because the type version can work for
16  * integers using std::integer_constant. The integer code is commented out below in case a work-around can be found.
17  */
18 
19 #ifndef SCARAB_UNIQUE_TYPELIST_HH_
20 #define SCARAB_UNIQUE_TYPELIST_HH_
21 
22 #include <type_traits>
23 
24 namespace scarab
25 {
26  // unique type check
27  template< typename T, typename FirstType, typename... OtherTypes >
29 
30  template< typename T, typename FirstType >
31  struct is_unique_impl< T, FirstType >
32  {
33  static const bool value = ! std::is_same< T, FirstType >::value;
34  };
35 
36  template< typename T, typename FirstType, typename... OtherTypes >
37  struct is_unique_impl
38  {
39  static const bool value = std::is_same< T, FirstType >::value ? false : is_unique_impl< T, OtherTypes... >::value;
40  };
41 
42  template< typename T, typename FirstType, typename... OtherTypes >
43  struct is_unique : std::integral_constant< bool, is_unique_impl< T, FirstType, OtherTypes... >::value >
44  {};
45 
46  // type list
47  template< typename... Types >
48  struct type_list {};
49 
50  // appending
51  template< typename T, typename... ListItems >
53 
54  template< typename T >
56  {
58  };
59 
60  template< typename T, typename... ListItems >
61  struct unique_append_impl< T, type_list< ListItems... > >
62  {
63  static_assert(is_unique< T, ListItems... >::value, "Non-unique type found");
64  using type = type_list< T, ListItems... >;
65  };
66 
67  template< typename T, typename List >
69 
70  // for debug printing
71  //template< typename T > struct debug_t;
72 
73  // test implementation
74 /* // this should work
75  using test_list_void = type_list<>;
76 #define TEST_LIST test_list_void
77 
78  typedef std::integral_constant< unsigned, 0 > zero_t;
79  using test_list_zero_t = unique_append< zero_t, TEST_LIST >;
80 #undef TEST_LIST
81 #define TEST_LIST test_list_zero_t
82 
83  typedef std::integral_constant< unsigned, 1 > one_t;
84  using test_list_one_t = unique_append< one_t, TEST_LIST >;
85 #undef TEST_LIST
86 #define TEST_LIST test_list_one_t
87 */
88 /* // this should fail
89  typedef std::integral_constant< unsigned, 1 > duplicate_t;
90  using test_list_duplicate_t = unique_append< duplicate_t, TEST_LIST >;
91 #undef TEST_LIST
92 #define TEST_LIST test_list_duplicate_t
93  //debug_t< TEST_LIST > d;
94 */
95 
96 
97 
98  // Integer lists
99  // Unfortunately this section doesn't quite work
100  // The problem comes in the partial specialization: struct append_impl_int< T, int_list< ListItems... > >
101  // This works when the unspecialized template uses a type parameter pack, but not when it uses an int parameter pack.
102  // The error I get is:
103  // error: template argument for non-type template parameter must be an expression
104 /*
105  // unique int check
106  template< int T, int FirstType, int... OtherTypes >
107  struct is_unique_impl_int;
108 
109  template< int T, int FirstType >
110  struct is_unique_impl_int< T, FirstType >
111  {
112  static const bool value = T != FirstType;
113  };
114 
115  template< int T, int FirstType, int... OtherTypes >
116  struct is_unique_impl_int
117  {
118  static const bool value = T == FirstType ? false : is_unique_impl_int< T, OtherTypes... >::value;
119  };
120 
121  template< int T, int FirstType, int... OtherTypes >
122  struct is_unique_int : std::integral_constant< bool, is_unique_impl_int< T, FirstType, OtherTypes... >::value >
123  {};
124 
125  // int list
126  template< int... Types >
127  struct int_list {};
128 
129  // appending
130  template< int T, int... ListItems >
131  struct unique_append_impl_int;
132 
133  template< int T >
134  struct unique_append_impl_int< T >
135  {
136  using type = int_list< T >;
137  };
138 
139  template< int T, int... ListItems >
140  struct unique_append_impl_int< T, int_list< ListItems... > >
141  {
142  static_assert(is_unique_int< T, ListItems... >::value, "Non-unique return code found");
143  using type = int_list< T, ListItems... >;
144  };
145 
146  template< int T, typename List >
147  using unique_append_int = typename unique_append_impl_int< T, List >::type;
148 
149 
150  // test implementation
151 
152  using test_list_void_int = list_int<>;
153 #define TEST_LIST_INT test_list_void_int
154 
155  const static int zero_int = 0;
156  using test_list_zero_int = append_int< zero_int, TEST_LIST_INT >;
157 #undef TEST_LIST_INT
158 #define TEST_LIST_INT test_list_zero_int
159 
160  const static int one_int = 1;
161  using test_list_one_int = unique_append_int< one_int, TEST_LIST_INT >;
162 #undef TEST_LIST_INT
163 #define TEST_LIST_INT test_list_one_int
164 */
165 /* // this should fail
166  const static int duplicate_int = 1;
167  using test_list_duplicate_t = unique_append< duplicate_int, TEST_LIST >;
168 #undef TEST_LIST
169 #define TEST_LIST test_list_duplicate_int
170  //debug_t< TEST_LIST > d;
171 */
172 
173 }
174 
175 #endif /* SCARAB_UNIQUE_TYPELIST_HH_ */
static const bool value
typename unique_append_impl< T, List >::type unique_append