qxLib
type_traits.h
Go to the documentation of this file.
1 /**
2 
3  @file type_traits.h
4  @author Khrapov
5  @data 10.09.2020
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 #pragma once
10 
11 #include <qx/meta/concepts.h>
12 
13 namespace qx
14 {
15 
16 // ------------------------------------------------- same_variadic_args ------------------------------------------------
17 
18 template<class...>
20 
21 template<class T>
22 struct same_variadic_args<T> : std::true_type
23 {
24  using type = T;
25 };
26 
27 template<class first_t, class second_t, class... rest_t>
28 struct same_variadic_args<first_t, second_t, rest_t...> : std::false_type
29 {
30 };
31 
32 // check if all of variadic arguments are same type
33 template<class first_t, class... rest_ty>
34 struct same_variadic_args<first_t, first_t, rest_ty...> : same_variadic_args<first_t, rest_ty...>
35 {
36 };
37 
38 template<class... args_t>
39 constexpr bool same_variadic_args_v = same_variadic_args<args_t...>::value;
40 
41 
42 
43 // ----------------------------------------------- specific_variadic_args ----------------------------------------------
44 
45 template<class T, class... args_t>
47 {
48  static constexpr bool value = std::conjunction_v<std::is_same<T, args_t>...>;
49 };
50 
51 template<class T, class... args_t>
52 static constexpr bool specific_variadic_args_v = specific_variadic_args<T, args_t...>::value;
53 
54 
55 // --------------------------------------------------- iterator_value --------------------------------------------------
56 
57 // get value type of iterator
58 template<class T, class = void>
60 {
61 };
62 
63 // default implementation with ::value_type
64 template<class T>
65 struct iterator_value<T, std::enable_if_t<is_iterator<T>>>
66 {
67  using type = typename T::value_type;
68 };
69 
70 // some iterators may be implemented as pointers
71 template<class T>
72 struct iterator_value<T, std::enable_if_t<std::is_pointer_v<T>>>
73 {
74  using type = std::remove_pointer_t<T>;
75 };
76 
77 template<class T>
78 using iterator_value_t = typename iterator_value<T>::type;
79 
80 
81 
82 // ---------------------------------------------- is_specialization_exist ----------------------------------------------
83 
84 namespace details
85 {
86 
87 template<class T, std::size_t = sizeof(T)>
88 std::true_type is_specialization_exist_impl(T*);
89 
90 std::false_type is_specialization_exist_impl(...);
91 
92 } // namespace details
93 
94 // decide if a struct/class specialization exist
95 template<class T>
96 using is_specialization_exist = decltype(details::is_specialization_exist_impl(std::declval<T*>()));
97 
98 template<class T>
99 constexpr bool is_specialization_exist_v = is_specialization_exist<T>::value;
100 
101 
102 
103 // ------------------------------------------------ is_specialization_of -----------------------------------------------
104 
105 template<class test_t, template<class...> class reference_t>
106 struct is_specialization_of : std::false_type
107 {
108 };
109 
110 template<template<class...> class reference_t, class... args_t>
111 struct is_specialization_of<reference_t<args_t...>, reference_t> : std::true_type
112 {
113 };
114 
115 // --------------------------------------------------- visit_overload --------------------------------------------------
116 
117 /**
118  @struct visit_overload
119  @details This struct allows to visit std::variant with lambdas
120  @note https://www.cppstories.com/2018/09/visit-variants/
121  @tparam args_t - lambda types
122 
123  @code
124  struct Fluid { };
125  struct LightItem { };
126  struct HeavyItem { };
127  struct FragileItem { };
128 
129  int main() {
130  std::variant<Fluid, LightItem, HeavyItem, FragileItem> package;
131 
132  std::visit(qx::visit_overload
133  {
134  [](const Fluid& ) { std::cout << "fluid\n"; },
135  [](const LightItem& ) { std::cout << "light item\n"; },
136  [](const auto&) { std::cout << "default\n"; }
137  },
138  package);
139  }
140  @endcode
141 **/
142 template<class... args_t>
143 struct visit_overload : args_t...
144 {
145  using args_t::operator()...;
146 };
147 
148 template<class... args_t>
149 visit_overload(args_t...) -> visit_overload<args_t...>;
150 
151 } // namespace qx