Nano
A C++ template metaprogramming library
list.hpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------------------------------------
2 /// @file list.hpp
3 /// @brief Header file for the list metaclass to provide compile time lists
4 // ----------------------------------------------------------------------------------------------------------
5 
6 /*
7  * ----------------------------------------------------------------------------------------------------------
8  * list header file for nano library.
9  * Copyright (C) 2015 Rob Clucas
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  * ----------------------------------------------------------------------------------------------------------
25  */
26 
27 #ifndef NANO_LIST_HPP
28 #define NANO_LIST_HPP
29 
30 #include <nano/functions.hpp>
31 #include <cassert>
32 
33 namespace nano {
34 
35 // ----------------------------------------------------------------------------------------------------------
36 /// @struct list
37 /// @brief Meta class that holds types, and allows functions to be applied to the elements of the list
38 /// using the internal apply struct. \n
39 /// \n
40 /// Usage: \n
41 /// \n
42 /// using nano::dim; \\ To get dimension types \n
43 /// using test_list = list<i, j, k, l>; \\ A list of dimensions \n
44 /// \n
45 /// using shifted_list = list::apply<shift>; \n
46 /// \n
47 /// Where shift is some function which operates on a type in the list
48 /// @tparam Ts The tyes of the elements in the list
49 // ----------------------------------------------------------------------------------------------------------
50 template <typename... Ts>
51 struct list
52 {
53  using type = list<Ts...>;
54 
55  static constexpr std::size_t size = sizeof...(Ts); //!< The size of the list
56 };
57 
58 // Define a list with no arguments
60 
61 // ---------------------------------------- Operations on a list(s) -----------------------------------------
62 
63 namespace detail {
64 
65 // ----------------------------------------------------------------------------------------------------------
66 /// @struct get
67 /// @brief Meta function to get an element from a list
68 /// @tparam Index The index of the element in the list to get
69 /// @tparam List The list to get the element from
70 // ----------------------------------------------------------------------------------------------------------
71 template <typename Index, typename List>
72 struct get;
73 
74 // Recursive case to look through the list
75 template <std::size_t Index, typename Head, typename... Tail>
76 struct get<nano::size_t<Index>, list<Head, Tail...>> : public get<nano::size_t<Index - 1>, list<Tail...>> {};
77 
78 // Base case (when we reach the 0 element)
79 template <typename Head, typename... Tail>
80 struct get<nano::size_t<0>, list<Head, Tail...>> : public identify<Head> {};
81 
82 }
83 
84 // Wrapper for getting
85 template <std::size_t Index, typename List>
86 using get = typename detail::get<nano::size_t<Index>, List>::result;
87 
88 // ----------------------------------------------------------------------------------------------------------
89 /// @struct find_type
90 /// @brief Find the index of a specific type in the list (the index of the first occurrence). \n
91 /// If the type is not found then the value 'parameter' will be -1.
92 /// @tparam Type The type to find
93 /// @tparam List The list to find the type in
94 // ----------------------------------------------------------------------------------------------------------
95 template <typename Type, typename List>
96 struct find_type;
97 
98 // Case to recurse
99 template <typename Type, typename Head, typename... Tail>
100 struct find_type<Type, list<Head, Tail...>>
101 {
102  static constexpr int next_result = find_type<Type, list<Tail...>>::result;
103 
104  // 'Move through list'
105  static constexpr int result = next_result >= 0 ? next_result + 1 : -1;
106 };
107 
108 // Case for when the type is found
109 template <typename Type, typename... Tail>
110 struct find_type<Type, list<Type, Tail...>>
111 {
112  static constexpr int result = 0;
113 };
114 
115 // Case for not found (Tail will be empty)
116 template <typename Type>
117 struct find_type<Type, list<>>
118 {
119  static constexpr int result = -1;
120 };
121 
122 // ----------------------------------------------------------------------------------------------------------
123 /// @struct type_not_present
124 /// @brief To check if a type in a list is not found. Where the find_type tries to find a type and get
125 /// its index to return, this function simply returns true of the type is not found, and false
126 /// if the tpe is found.
127 /// @tparam Type The type to check the presence of
128 /// @tparam List The list to look through
129 // ----------------------------------------------------------------------------------------------------------
130 template <typename Type, typename List>
132 
133 // Recursive case
134 template <typename Type, typename Head, typename... Tail>
135 struct type_not_present<Type, list<Head, Tail...>>
136 {
137  // The list must remain the same (the type
138  // changes which gives different results)
139  static constexpr bool constant_list = true;
140 
141  static constexpr int next_result = type_not_present<Type, list<Tail...>>::result;
142 
143  // 'Move through list'
144  static constexpr int result = next_result <= 0 ? 0 : next_result + 1;
145 };
146 
147 // Case for when the type is found
148 template <typename Type, typename... Tail>
149 struct type_not_present<Type, list<Type, Tail...>>
150 {
151  static constexpr bool constant_list = true;
152 
153  static constexpr int result = 0;
154 };
155 
156 // Case for not found (Tail will be empty)
157 template <typename Type>
158 struct type_not_present<Type, list<>>
159 {
160  static constexpr bool constant_list = true;
161 
162  static constexpr int result = 1;
163 };
164 
165 // ----------------------------------------------------------------------------------------------------------
166 /// @struct first_not_present
167 /// @brief Just check if the first element of the list was found (searching should be done beforehand)
168 /// @tparam Type This is just a placeholder to conform to the Evaluator interface for the filter
169 /// function
170 /// @tparam List The list to check if the first element was not found
171 // ----------------------------------------------------------------------------------------------------------
172 template <typename Type, typename List>
174 
175 template <typename Type, typename Head, typename... Tail>
176 struct first_not_present<Type, list<Head, Tail...>>
177 {
178  // The list must change (to get different results the
179  // head of the list must be removed for the next it
180  static constexpr bool constant_list = false;
181 
182  static constexpr bool result = Head::value == -1 ? true : false;
183 };
184 
185 // ----------------------------------------------------------------------------------------------------------
186 /// @struct join
187 /// @brief Joins two lists
188 /// @tparam List1 The first list to join
189 /// @tparam List2 The second list to join
190 // ----------------------------------------------------------------------------------------------------------
191 template <typename List1, typename List2>
192 struct join;
193 
194 // Specialization for using list types
195 template <typename... Ts, typename... Us>
196 struct join<list<Ts...>, list<Us...>> : public identify<list<Ts..., Us...>> {};
197 
198 } // End namespace nano
199 
200 #endif // NANO_LIST_HPP
Just check if the first element of the list was found (searching should be done beforehand) ...
Definition: list.hpp:173
Simply an identifier to identify meta types and meta functions.
Definition: eval.hpp:40
Definition: containers.hpp:34
Joins two lists.
Definition: list.hpp:192
Find the index of a specific type in the list (the index of the first occurrence). If the type is not found then the value 'parameter' will be -1.
Definition: list.hpp:96
Meta class that holds types, and allows functions to be applied to the elements of the list using the...
Definition: list.hpp:51
To check if a type in a list is not found. Where the find_type tries to find a type and get its index...
Definition: list.hpp:131
static constexpr std::size_t size
The size of the list.
Definition: list.hpp:55
Meta function to get an element from a list.
Definition: list.hpp:72
Wrapper around size_t for static size_t types used by metaclass and metafunctions in nano...
Definition: numeric_types.hpp:40