coveo::linq
Implementation of .NET-like LINQ operators in C++
enumerable_detail.h
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Implementation details of coveo::enumerable.
4  *
5  * This file contains implementation details used by coveo::enumerable.
6  * It should not be necessary to use this file directly when using the class.
7  * Code in the <tt>coveo::detail</tt> namespace is subject to change
8  * in-between versions.
9  *
10  * @copyright 2016-2019, Coveo Solutions Inc.
11  * Distributed under the Apache License, Version 2.0 (see <a href="https://github.com/coveo/linq/blob/master/LICENSE">LICENSE</a>).
12  */
13 
14 #ifndef COVEO_ENUMERABLE_DETAIL_H
15 #define COVEO_ENUMERABLE_DETAIL_H
16 
17 #include <cstdint>
18 #include <functional>
19 #include <iterator>
20 #include <type_traits>
21 #include <utility>
22 
23 namespace coveo {
24 namespace detail {
25 
26 /**
27  * @internal
28  * @brief Type trait that detects @c begin.
29  * @headerfile enumerable_detail.h <coveo/seq/detail/enumerable_detail.h>
30  *
31  * Type trait that can be used to know if <tt>std::begin(T)</tt> is valid.
32  * Detects both <tt>std::begin()</tt> specializations and <tt>begin()</tt> methods.
33  *
34  * @tparam Type for which we need @c begin.
35  */
36 template<typename T>
37 class has_begin
38 {
39  static_assert(sizeof(std::int_least8_t) != sizeof(std::int_least32_t),
40  "has_begin only works if int_least8_t has a different size than int_least32_t");
41 
42  template<typename C> static std::int_least8_t test(decltype(std::begin(std::declval<C>()))*); // Will be selected if std::begin(C) works
43  template<typename C> static std::int_least32_t test(...); // Will be selected otherwise
44 public:
45  static constexpr bool value = sizeof(test<T>(nullptr)) == sizeof(std::int_least8_t);
46 };
47 
48 /**
49  * @internal
50  * @brief Type trait that detects @c end.
51  * @headerfile enumerable_detail.h <coveo/seq/detail/enumerable_detail.h>
52  *
53  * Type trait that can be used to know if <tt>std::end(T)</tt> is valid.
54  * Detects both <tt>std::end()</tt> specializations and <tt>end()</tt> methods.
55  *
56  * @tparam Type for which we need @c end.
57  */
58 template<typename T>
59 class has_end
60 {
61  static_assert(sizeof(std::int_least8_t) != sizeof(std::int_least32_t),
62  "has_end only works if int_least8_t has a different size than int_least32_t");
63 
64  template<typename C> static std::int_least8_t test(decltype(std::end(std::declval<C>()))*); // Will be selected if std::end(C) works
65  template<typename C> static std::int_least32_t test(...); // Will be selected otherwise
66 public:
67  static const bool value = sizeof(test<T>(nullptr)) == sizeof(std::int_least8_t);
68 };
69 
70 /**
71  * @internal
72  * @brief Type trait that detects @c size.
73  * @headerfile enumerable_detail.h <coveo/seq/detail/enumerable_detail.h>
74  *
75  * Type trait that can be used to know if type @c T has a <tt>size()</tt>
76  * @c const method that returns a non-<tt>void</tt> result.
77  *
78  * @tparam Type for which we need @c size.
79  */
80 template<typename T>
81 class has_size_const_method
82 {
83  static_assert(sizeof(std::int_least8_t) != sizeof(std::int_least32_t),
84  "has_size_const_method only works if int_least8_t has a different size than int_least32_t");
85 
86  template<typename C> static std::int_least8_t test(typename std::enable_if<!std::is_void<decltype(std::declval<const C>().size())>::value, void*>::type); // Will be selected if C has size() that does not return void
87  template<typename C> static std::int_least32_t test(...); // Will be selected otherwise
88 public:
89  static const bool value = sizeof(test<T>(nullptr)) == sizeof(std::int_least8_t);
90 };
91 
92 } // detail
93 } // coveo
94 
95 #endif // COVEO_ENUMERABLE_DETAIL_H