UgMisc 0.2-110
Miscellaneous C++ header library
Loading...
Searching...
No Matches
sfinae_helpers.hpp
Go to the documentation of this file.
1/*
2 * SPDX-Licence-Identifier: MIT
3 *
4 * Copyright 2025-2026 Larry Chips
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the “Software”), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#ifndef UGMISC_SFINAE_HELPERS_HPP
25#define UGMISC_SFINAE_HELPERS_HPP
26
42
43#include <limits>
44#include <type_traits>
45#include <utility>
46
47#include "ugmisc/features.hpp"
48
49
50
51
52namespace ugmisc {
53
54
55
56
57template<class T>
58using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
59
60
61
62
63template<class T>
64using plain_ref_t = std::remove_cv_t<T>&;
65
66
67
68
69template<class T> plain_ref_t<T> decl_plain_ref();
70
71
72
73
74namespace _sfinae {
75
76template<class T, class=void>
77struct get_is_bitwise : std::false_type {};
78
79
80
81
82template<class T>
83struct get_is_bitwise<
84 T,
85 std::void_t<
86 decltype(decl_plain_ref<T>() = std::declval<T>() | std::declval<T>()),
87 decltype(decl_plain_ref<T>() = std::declval<T>() & std::declval<T>()),
88 decltype(decl_plain_ref<T>() = std::declval<T>() ^ std::declval<T>()),
89 decltype(decl_plain_ref<T>() = ~ std::declval<T>())
90 >
91 >
92 : public std::true_type {};
93
94} /* _sfinae (::ugmisc::_sfinae) */
95
96
97
98
109template<class T>
110static constexpr bool is_bitwise = _sfinae::get_is_bitwise<T>::value;
111#ifdef UGMISC_USE_CONCEPT_DECLS
116template<class T>
117concept Bitwise = is_bitwise<T>;
118#endif
119
120
121
122
126template<class T, class R=T> using uint_only = std::enable_if_t<
127 std::numeric_limits<T>::is_integer
128 && ( ! std::numeric_limits<T>::is_signed ),
129
130 R
131 >;
132#ifdef UGMISC_USE_CONCEPT_DECLS
138template<class T>
139concept Uint =
140 std::numeric_limits<T>::is_integer
141 && ! std::numeric_limits<T>::is_signed
142 ;
143
147# define UGMISC_UINT_RETURN(T, R) R requires ::ugmisc::Uint<T>
148#else
149# define UGMISC_UINT_RETURN(T, R) ::ugmisc::uint_only<T, R>
150#endif
151
152
153
154
158template<class T, class R=T> using modulo_uint_only = std::enable_if_t<
159 std::numeric_limits<T>::is_integer
160 && ( ! std::numeric_limits<T>::is_signed )
161 && std::numeric_limits<T>::is_modulo
162 && std::is_arithmetic_v<T>,
163
164 R
165 >;
166#ifdef UGMISC_USE_CONCEPT_DECLS
172template<class T>
173concept ModuloUint =
174 Uint<T> && std::numeric_limits<T>::is_modulo
175 && std::is_arithmetic_v<T>
176 ;
177#endif
178
179
180
181
182/*
183 * See below.
184 */
185template<class T> static constexpr bool is_bitwise_uint =
186 std::numeric_limits<T>::is_integer
187 && ( ! std::numeric_limits<T>::is_signed )
188 && ( std::numeric_limits<T>::radix == 2 )
189 && std::numeric_limits<T>::is_modulo
190 && std::is_arithmetic_v<T>
191 && is_bitwise<T>
192 ;
193
208template<class T, class R=T> using bitwise_uint_only = std::enable_if_t<
209 is_bitwise_uint<T>,
210 R
211 >;
212#ifdef UGMISC_USE_CONCEPT_DECLS
219template<class T> concept BitwiseUint = Bitwise<T> && ModuloUint<T>;
220
224# define UGMISC_BITWISE_UINT_RETURN(T, R) R requires ::ugmisc::BitwiseUint<T>
225#else
226# define UGMISC_BITWISE_UINT_RETURN(T, R) ::ugmisc::bitwise_uint_only<T, R>
227#endif
228
229
230
231
235template<class T, class R=T> using int_only = std::enable_if_t<
236 std::numeric_limits<T>::is_integer,
237
238 R
239 >;
240#ifdef UGMISC_USE_CONCEPT_DECLS
247template<class T> concept Int = std::numeric_limits<T>::is_integer;
248#endif
249} /* ugmisc */
250
251#endif /* UGMISC_SFINAE_HELPERS_HPP */
Definition sfinae_helpers.hpp:117
Definition sfinae_helpers.hpp:219
Definition sfinae_helpers.hpp:247
Definition sfinae_helpers.hpp:173
Definition sfinae_helpers.hpp:139
Feature detection.
std::enable_if_t< std::numeric_limits< T >::is_integer, R > int_only
Definition sfinae_helpers.hpp:235
std::enable_if_t< is_bitwise_uint< T >, R > bitwise_uint_only
Definition sfinae_helpers.hpp:208
std::enable_if_t< std::numeric_limits< T >::is_integer &&(! std::numeric_limits< T >::is_signed) &&std::numeric_limits< T >::is_modulo &&std::is_arithmetic_v< T >, R > modulo_uint_only
Resolves to R if T is an unsigned integer with modulo arithmetic.
Definition sfinae_helpers.hpp:158
std::enable_if_t< std::numeric_limits< T >::is_integer &&(! std::numeric_limits< T >::is_signed), R > uint_only
Resolves to R if T is an unsigned integer.
Definition sfinae_helpers.hpp:126