1 //  typelist.hpp
2 //
3 //  Copyright (c) 2003 Eugene Gladyshev
4 //
5 //  Permission to copy, use, modify, sell and distribute this software
6 //  is granted provided this copyright notice appears in all copies.
7 //  This software is provided "as is" without express or implied
8 //  warranty, and with no claim as to its suitability for any purpose.
9 //
10 
11 #ifndef __ttl_typelist__hpp
12 #define __ttl_typelist__hpp
13 
14 #include "settings/extern/ttl/config.hpp"
15 #include "settings/extern/ttl/data_holder.hpp"
16 #include "settings/extern/ttl/exception.hpp"
17 #include "settings/extern/ttl/macro_params.hpp"
18 #include "settings/extern/ttl/equivalent_types.hpp"
19 #include "settings/extern/ttl/meta/is_same.hpp"
20 #include "settings/extern/ttl/selector.hpp"
21 
22 
23 namespace ttl
24 {
25 namespace meta
26 {
27 struct exception : ttl::exception
28 {
exceptionttl::meta::exception29     exception() : ttl::exception("typelist error") {}
30 };
31 //internal implementation
32 namespace impl
33 {
34     ////////////////////////////////////////////////////////////
35     template< TTL_TPARAMS_DEF(TTL_MAX_TYPELIST_PARAMS, empty_type) >
36     struct typelist_traits
37     {
38         typedef typelist_traits< TTL_ARGS_S(TTL_DEC(TTL_MAX_TYPELIST_PARAMS)) > tail;
39 
40         enum
41         {
42             length = 1 + tail::length
43         };
44 
45         typedef typename selector< sizeof(ttl::data_holder<T1>) >=sizeof(ttl::data_holder<typename tail::largest_type>),
46             T1,
47             typename tail::largest_type
48             >::type largest_type;
49     };
50 
51     template<>
52     struct typelist_traits< TTL_LIST_ITEMS(TTL_MAX_TYPELIST_PARAMS,empty_type) >
53     {
54         typedef empty_type tail;
55         enum
56         {
57             length = 0
58         };
59         typedef empty_type largest_type;
60     };
61 
62     ////////////////////////////////////////////////////////////
63     //
64     //Instantiate TTL_MAX_TYPELIST_PARAMS get<> templates
65     //	template<typename T>  struct get<T, 0>
66     //	{
67     //		enum { index = 0 };
68     //		typedef typename T::type1 type;
69     //	};
70     //
71     //	template<typename T>  struct get<T, 1>
72     //	{
73     //		enum { index = 1 };
74     //		typedef typename T::type2 type;
75     //	};
76     //	...
77     //
78 
79     template< typename T, int N > struct get;
80     #define TTL_META_TYPELIST_GET(n, t) template<typename T>  struct get<T, TTL_CNTDEC_##n>  \
81     { enum {index = n-1}; typedef typename T::t##n type; };
82 
83     TTL_REPEAT( TTL_MAX_TYPELIST_PARAMS, TTL_META_TYPELIST_GET, TTL_META_TYPELIST_GET, type )
84 
85     #undef TTL_META_TYPELIST_GET
86 }
87 
88     template < TTL_TPARAMS_DEF(TTL_MAX_TYPELIST_PARAMS, empty_type) >
89     struct typelist
90     {
91         TTL_TYPEDEFS(TTL_MAX_TYPELIST_PARAMS)
92 
93         typedef impl::typelist_traits< TTL_ARGS(TTL_MAX_TYPELIST_PARAMS) > list_traits;
94 
95         enum{ length = list_traits::length };
96         typedef typename list_traits::largest_type largest_type;
97     };
98 
99     ////////////////////////////////////////////////////////////
100     template < typename L >
101     struct length
102     {
103         enum { value = L::length };
104     };
105 
106     ///////////////////////////////////////////////////////////
107     template< typename L, int N, bool Ok = (N < length<L>::value) >
108     struct get
109     {
110         typedef typename impl::get<L,N>::type type;
111         enum{ index = N };
112     };
113 
114     template< typename L, int N >
115     struct get<L,N,false>
116     {
117         //index is out of range
118     };
119 
120     ////////////////////////////////////////////////////////////
121     //	run-time type switch
122     template <typename L, int N = 0, bool Stop=(N==length<L>::value) > struct type_switch;
123 
124     template <typename L, int N, bool Stop>
125     struct type_switch
126     {
127         template< typename F >
operator ()ttl::meta::type_switch128         void operator()( size_t i, F& f )
129         {
130             if( i == N )
131             {
132                 // Edited(BM) 07/05/16 added the 'template'
133                 // f.operator()<typename impl::get<L,N>::type>();
134                 f.template operator()<typename impl::get<L,N>::type>();
135             }
136             else
137             {
138                 type_switch<L, N+1> next;
139                 next(i, f);
140             }
141         }
142     };
143 
144     template <typename L, int N>
145     struct type_switch<L, N, true>
146     {
147         template< typename F >
operator ()ttl::meta::type_switch148         void operator()( size_t /*i*/, F& /*f*/ )
149         {
150             throw meta::exception();
151         }
152     };
153 
154 
155     //////////////////////////////////////////////////////////////
156     template< typename T, typename L, int N = 0, bool Stop=(N>=length<L>::value) >
157     struct find_equivalent_type
158     {
159     private:
160         typedef impl::get<L,N> get_type;
161 
162         typedef typename selector< equivalent_types<typename get_type::type, T>::value,
163             get_type,
164             find_equivalent_type<T,L,N+1>
165             >::type found;
166 
167     public:
168         typedef typename found::type type;
169         enum {index = found::index};
170     };
171 
172     template<typename T, typename L, int N>
173     struct find_equivalent_type<T, L, N, true>
174     {
175     };
176 
177 
178     //////////////////////////////////////////////
179     template< typename T, typename L, int N = 0, bool Stop=(N>=length<L>::value) >
180     struct find
181     {
182     private:
183         typedef impl::get<L,N> get_type;
184 
185         typedef typename selector< is_same<typename get_type::type, T>::value,
186             get_type,
187             find<T,L,N+1>
188             >::type found;
189 
190     public:
191         typedef typename found::type type;
192         enum {index = found::index};
193     };
194 
195     template<typename T, typename L, int N>
196     struct find<T, L, N, true>
197     {
198     };
199 
200 }
201 }
202 
203 #endif //__typelist__hpp
204