A library for working with phylogenetic and population genetic data.
v0.27.0
type_traits.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CORE_TYPE_TRAITS_H_
2 #define GENESIS_UTILS_CORE_TYPE_TRAITS_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2022 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
34 #include <iterator>
35 #include <type_traits>
36 
37 namespace genesis {
38 namespace utils {
39 
40 // =================================================================================================
41 // Basics
42 // =================================================================================================
43 
49 template <typename... >
50 using void_t = void;
51 
52 // =================================================================================================
53 // Iterator Categories
54 // =================================================================================================
55 
56 // Maybe I'm missing something, but as far as I could figure this out, in C++11, which does not
57 // have Concepts yet, there is no standard way of checking that an iterator is *at least* of a
58 // particular category... So let's implement that ourselves.
59 // Inspired from https://stackoverflow.com/a/25291412/4184258
60 
61 // -------------------------------------------------------------------------
62 // is_iterator_tag_based
63 // -------------------------------------------------------------------------
64 
80 template <class T, typename = void>
81 struct is_iterator_tag_based : std::false_type {};
82 
98 template <class T>
100 <T, typename std::enable_if<
101  std::is_base_of<
102  std::input_iterator_tag, typename std::iterator_traits<T>::iterator_category
103  >::value ||
104  std::is_same<
105  std::output_iterator_tag, typename std::iterator_traits<T>::iterator_category
106  >::value
107 >::type> : std::true_type {};
108 
109 // -------------------------------------------------------------------------
110 // is_input_iterator_tag_based
111 // -------------------------------------------------------------------------
112 
118 template <class T, class = void>
119 struct is_input_iterator_tag_based : std::false_type {};
120 
126 template <class T>
128 <T, typename std::enable_if<
129  std::is_base_of<
130  std::input_iterator_tag, typename std::iterator_traits<T>::iterator_category
131  >::value
132 >::type> : std::true_type {};
133 
134 // -------------------------------------------------------------------------
135 // is_output_iterator_tag_based
136 // -------------------------------------------------------------------------
137 
143 template <class T, class = void>
144 struct is_output_iterator_tag_based : std::false_type {};
145 
151 template <class T>
153 <T, typename std::enable_if<
154  std::is_base_of<
155  std::output_iterator_tag, typename std::iterator_traits<T>::iterator_category
156  >::value
157 >::type> : std::true_type {};
158 
159 // -------------------------------------------------------------------------
160 // is_forward_iterator_tag_based
161 // -------------------------------------------------------------------------
162 
168 template <class T, class = void>
169 struct is_forward_iterator_tag_based : std::false_type {};
170 
176 template <class T>
178 <T, typename std::enable_if<
179  std::is_base_of<
180  std::forward_iterator_tag, typename std::iterator_traits<T>::iterator_category
181  >::value
182 >::type> : std::true_type {};
183 
184 // -------------------------------------------------------------------------
185 // is_bidirectional_iterator_tag_based
186 // -------------------------------------------------------------------------
187 
193 template <class T, class = void>
194 struct is_bidirectional_iterator_tag_based : std::false_type {};
195 
201 template <class T>
203 <T, typename std::enable_if<
204  std::is_base_of<
205  std::bidirectional_iterator_tag, typename std::iterator_traits<T>::iterator_category
206  >::value
207 >::type> : std::true_type {};
208 
209 // -------------------------------------------------------------------------
210 // is_random_access_iterator_tag_based
211 // -------------------------------------------------------------------------
212 
218 template <class T, class = void>
219 struct is_random_access_iterator_tag_based : std::false_type {};
220 
226 template <class T>
228 <T, typename std::enable_if<
229  std::is_base_of<
230  std::random_access_iterator_tag, typename std::iterator_traits<T>::iterator_category
231  >::value
232 >::type> : std::true_type {};
233 
234 // =================================================================================================
235 // Iterator Properties
236 // =================================================================================================
237 
238 // -------------------------------------------------------------------------
239 // has_input_iterator_properties
240 // -------------------------------------------------------------------------
241 
242 template <class T, class = void>
243 struct has_input_iterator_properties : std::false_type {};
244 
245 template <class T>
247  void_t<decltype(++std::declval<T&>()), // incrementable,
248  decltype(*std::declval<T&>()), // dereferencable,
249  decltype(std::declval<T&>() == std::declval<T&>())>> // comparable
250  : std::true_type {};
251 
252 } // namespace utils
253 } // namespace genesis
254 
255 #endif // include guard
genesis::utils::is_input_iterator_tag_based
Return whether a type is an at least input iterator.
Definition: type_traits.hpp:119
genesis::utils::is_output_iterator_tag_based
Return whether a type is an at least output iterator.
Definition: type_traits.hpp:144
genesis::utils::is_bidirectional_iterator_tag_based
Return whether a type is at least a bidirectional iterator.
Definition: type_traits.hpp:194
genesis::utils::void_t
void void_t
Define void type for C++11.
Definition: type_traits.hpp:50
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::is_forward_iterator_tag_based
Return whether a type is at least a forward iterator.
Definition: type_traits.hpp:169
genesis::utils::is_iterator_tag_based
Return whether a type is an iterator.
Definition: type_traits.hpp:81
genesis::utils::is_random_access_iterator_tag_based
Return whether a type is at least a random access iterator.
Definition: type_traits.hpp:219
genesis::utils::has_input_iterator_properties
Definition: type_traits.hpp:243