ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkConceptChecking.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18/*=========================================================================
19 *
20 * Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21 *
22 * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23 *
24 * For complete copyright, license and disclaimer of warranty information
25 * please refer to the NOTICE file at the top of the ITK source tree.
26 *
27 *=========================================================================*/
28#ifndef itkConceptChecking_h
29#define itkConceptChecking_h
30
31#include "itkPixelTraits.h"
32#include "itkNumericTraits.h"
33#include <iostream>
34#include <type_traits>
35
43#define itkConceptMacro(name, conceptType) \
44 static_assert(::itk::Concept::Detail::IsSatisfied<void conceptType>::value, \
45 "ITK concept check failed: " #name " " #conceptType)
46
47namespace itk::Concept
48{
49namespace Detail
50{
52template <typename TSignature>
54template <typename TConcept>
55struct IsSatisfied<void(TConcept)> : TConcept
56{};
57
58template <typename TVoid, template <typename...> typename TExpression, typename... TArgs>
59struct IsValidExpressionImpl : std::false_type
60{};
61template <template <typename...> typename TExpression, typename... TArgs>
62struct IsValidExpressionImpl<std::void_t<TExpression<TArgs...>>, TExpression, TArgs...> : std::true_type
63{};
64
65template <template <typename...> typename TExpression, typename... TArgs>
66inline constexpr bool IsValidExpression = IsValidExpressionImpl<void, TExpression, TArgs...>::value;
67
68template <typename TBoolean>
69using RequireBoolean = std::enable_if_t<std::is_convertible_v<TBoolean, bool>>;
70template <typename T>
71T &
72Lvalue(); // Shorthand for std::declval<T &>(), only used in unevaluated operands.
73
74template <typename T1, typename T2>
75using StaticCast = decltype(static_cast<T2>(Lvalue<T1>()));
76template <typename T1, typename T2>
77using LessThan = std::void_t<RequireBoolean<decltype(Lvalue<T1>() < Lvalue<T2>())>,
78 RequireBoolean<decltype(Lvalue<T1>() <= Lvalue<T2>())>>;
79template <typename T1, typename T2>
80using GreaterThan = std::void_t<RequireBoolean<decltype(Lvalue<T1>() > Lvalue<T2>())>,
81 RequireBoolean<decltype(Lvalue<T1>() >= Lvalue<T2>())>>;
82ITK_GCC_PRAGMA_PUSH
83ITK_GCC_SUPPRESS_Wfloat_equal
84template <typename T1, typename T2>
85using Equality = std::void_t<RequireBoolean<decltype(Lvalue<T1>() == Lvalue<T2>())>,
86 RequireBoolean<decltype(Lvalue<T1>() != Lvalue<T2>())>>;
87ITK_GCC_PRAGMA_POP
88template <typename T1, typename T2, typename T3>
89using Additive = std::void_t<decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() + Lvalue<const T2>())),
90 decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() - Lvalue<const T2>()))>;
91template <typename T1, typename T2>
93 std::void_t<decltype(Lvalue<T2>() += Lvalue<const T1>()), decltype(Lvalue<T2>() -= Lvalue<const T1>())>;
94template <typename T1, typename T2, typename T3>
95using Multiply = decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() * Lvalue<const T2>()));
96template <typename T1, typename T2>
98template <typename T1, typename T2, typename T3>
99using Division = decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() / Lvalue<const T2>()));
100template <typename T1, typename T2>
102template <typename T1, typename T2, typename T3>
103using Bitwise = std::void_t<decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() & Lvalue<const T2>())),
104 decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() | Lvalue<const T2>())),
105 decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>() ^ Lvalue<const T2>())),
106 decltype(Lvalue<T3>() &= static_cast<T3>(Lvalue<const T2>())),
107 decltype(Lvalue<T3>() |= static_cast<T3>(Lvalue<const T2>())),
108 decltype(Lvalue<T3>() ^= static_cast<T3>(Lvalue<const T2>()))>;
109template <typename T1, typename T2, typename T3>
110using Bracket = decltype(Lvalue<T3>() = static_cast<T3>(Lvalue<const T1>()[Lvalue<const T2>()]));
111template <typename T>
112using Not = decltype(Lvalue<T>() = !Lvalue<T>());
113template <typename T>
115 std::void_t<decltype(Lvalue<T>()++), decltype(Lvalue<T>()--), decltype(++Lvalue<T>()), decltype(--Lvalue<T>())>;
116template <typename T>
118template <typename T, typename TTraits = NumericTraits<T>>
119using NumericTraitsMembers = std::void_t<typename TTraits::ValueType,
120 typename TTraits::PrintType,
121 typename TTraits::AbsType,
122 typename TTraits::AccumulateType,
123 typename TTraits::RealType,
124 typename TTraits::ScalarRealType,
125 typename TTraits::FloatType,
126 decltype(Lvalue<T>() = TTraits::NonpositiveMin(Lvalue<const T>())),
127 decltype(Lvalue<T>() = TTraits::ZeroValue(Lvalue<const T>())),
128 decltype(Lvalue<T>() = TTraits::OneValue(Lvalue<const T>())),
129 RequireBoolean<decltype(TTraits::IsPositive(Lvalue<const T>()))>,
130 RequireBoolean<decltype(TTraits::IsNonpositive(Lvalue<const T>()))>,
131 RequireBoolean<decltype(TTraits::IsNegative(Lvalue<const T>()))>,
132 RequireBoolean<decltype(TTraits::IsNonnegative(Lvalue<const T>()))>>;
134template <typename T>
135inline constexpr bool IsPrimaryNumericTraits =
136 std::is_base_of_v<std::numeric_limits<T>, NumericTraits<T>> && !std::numeric_limits<T>::is_specialized;
137template <typename T>
139 std::void_t<typename PixelTraits<T>::ValueType,
140 std::enable_if_t<std::is_convertible_v<decltype(PixelTraits<T>::Dimension), unsigned int>>>;
141template <typename T>
142using ValueTypeMember = typename T::ValueType;
143template <typename T1, typename T2>
145template <typename T>
146inline constexpr bool IsExact = std::numeric_limits<typename NumericTraits<T>::ValueType>::is_exact;
147} // namespace Detail
148
150template <typename T>
151struct DefaultConstructible : std::is_default_constructible<T>
152{};
153template <typename T>
154struct CopyConstructible : std::is_copy_constructible<T>
155{};
156
157template <typename T1, typename T2>
158struct Convertible : std::bool_constant<Detail::IsValidExpression<Detail::StaticCast, T1, T2>>
159{};
160template <typename T>
161struct Assignable : std::bool_constant<std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>>
162{};
163
164template <typename T1, typename T2 = T1>
165struct LessThanComparable : std::bool_constant<Detail::IsValidExpression<Detail::LessThan, T1, T2>>
166{};
167
168template <typename T1, typename T2 = T1>
169struct GreaterThanComparable : std::bool_constant<Detail::IsValidExpression<Detail::GreaterThan, T1, T2>>
170{};
171
172template <typename T1, typename T2 = T1>
173struct EqualityComparable : std::bool_constant<Detail::IsValidExpression<Detail::Equality, T1, T2>>
174{};
175
176template <typename T1, typename T2 = T1>
178 : std::bool_constant<LessThanComparable<T1, T2>::value && GreaterThanComparable<T1, T2>::value &&
179 EqualityComparable<T1, T2>::value>
180{};
181
182template <typename T1, typename T2 = T1, typename T3 = T1>
183struct AdditiveOperators : std::bool_constant<Detail::IsValidExpression<Detail::Additive, T1, T2, T3>>
184{};
185
186template <typename T1, typename T2 = T1>
187struct AdditiveAndAssignOperators : std::bool_constant<Detail::IsValidExpression<Detail::AdditiveAndAssign, T1, T2>>
188{};
189
190template <typename T1, typename T2 = T1, typename T3 = T1>
191struct MultiplyOperator : std::bool_constant<Detail::IsValidExpression<Detail::Multiply, T1, T2, T3>>
192{};
193
194template <typename T1, typename T2 = T1>
195struct MultiplyAndAssignOperator : std::bool_constant<Detail::IsValidExpression<Detail::MultiplyAndAssign, T1, T2>>
196{};
197
198template <typename T1, typename T2 = T1, typename T3 = T1>
199struct DivisionOperators : std::bool_constant<Detail::IsValidExpression<Detail::Division, T1, T2, T3>>
200{};
201
202template <typename T1, typename T2 = T1>
203struct DivisionAndAssignOperators : std::bool_constant<Detail::IsValidExpression<Detail::DivisionAndAssign, T1, T2>>
204{};
205
206template <typename T1, typename T2 = T1, typename T3 = T1>
207struct BitwiseOperators : std::bool_constant<Detail::IsValidExpression<Detail::Bitwise, T1, T2, T3>>
208{};
209
210template <typename T1, typename T2 = T1, typename T3 = T1>
211struct BracketOperator : std::bool_constant<Detail::IsValidExpression<Detail::Bracket, T1, T2, T3>>
212{};
213template <typename T>
214struct NotOperator : std::bool_constant<Detail::IsValidExpression<Detail::Not, T>>
215{};
216template <typename T>
217struct IncrementDecrementOperators : std::bool_constant<Detail::IsValidExpression<Detail::IncrementDecrement, T>>
218{};
219template <typename T>
220struct OStreamWritable : std::bool_constant<Detail::IsValidExpression<Detail::OStreamWrite, T>>
221{};
222template <typename T>
223struct Signed : std::bool_constant<NumericTraits<T>::is_signed>
224{};
225template <typename T1, typename T2>
226struct SameType : std::is_same<T1, T2>
227{};
228template <unsigned int D1, unsigned int D2>
229struct SameDimension : std::bool_constant<D1 == D2>
230{};
231
232template <typename T>
234 : std::bool_constant<!Detail::IsPrimaryNumericTraits<T> && std::is_default_constructible_v<T> &&
235 Detail::IsValidExpression<Detail::NumericTraitsMembers, T>>
236{};
237template <typename T>
238struct HasPixelTraits : std::bool_constant<Detail::IsValidExpression<Detail::PixelTraitsMembers, T>>
239{};
240template <typename T>
241struct HasValueType : std::bool_constant<Detail::IsValidExpression<Detail::ValueTypeMember, T>>
242{};
243template <typename T>
244struct HasZero : std::is_default_constructible<T>
245{};
246template <typename T1, typename T2>
247struct HasJoinTraits : std::bool_constant<Detail::IsValidExpression<Detail::JoinTraitsMember, T1, T2>>
248{};
249
250template <unsigned int D1, unsigned int D2>
251struct SameDimensionOrMinusOne : std::bool_constant<D2 == D1 || D2 == D1 - 1>
252{};
253
254template <unsigned int D1, unsigned int D2>
255struct SameDimensionOrMinusOneOrTwo : std::bool_constant<D2 == D1 || D2 == D1 - 1 || D2 == D1 - 2>
256{};
257template <typename T>
258struct IsInteger : std::is_integral<T>
259{};
260
261template <typename T>
262struct IsUnsignedInteger : std::bool_constant<!NumericTraits<T>::is_signed>
263{};
264template <typename T>
265struct IsNonInteger : std::bool_constant<!std::is_integral_v<T>>
266{};
267
268template <typename T>
269struct IsFloatingPoint : std::bool_constant<!std::is_integral_v<T> && !Detail::IsExact<T>>
270{};
271
272template <typename T>
273struct IsFixedPoint : std::bool_constant<!std::is_integral_v<T> && Detail::IsExact<T>>
274{};
275} // namespace itk::Concept
276
277#endif
Define additional traits for native types such as int or float.
Traits for a pixel that define the dimension and component type.
std::void_t< decltype(Lvalue< T2 >()+=Lvalue< const T1 >()), decltype(Lvalue< T2 >() -=Lvalue< const T1 >())> AdditiveAndAssign
std::void_t< typename PixelTraits< T >::ValueType, std::enable_if_t< std::is_convertible_v< decltype(PixelTraits< T >::Dimension), unsigned int > > > PixelTraitsMembers
decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >() *Lvalue< const T2 >())) Multiply
std::void_t< decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >()+Lvalue< const T2 >())), decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >() - Lvalue< const T2 >()))> Additive
decltype(Lvalue< std::ostream >()<< Lvalue< T >()) OStreamWrite
decltype(Lvalue< T >()=!Lvalue< T >()) Not
std::void_t< typename TTraits::ValueType, typename TTraits::PrintType, typename TTraits::AbsType, typename TTraits::AccumulateType, typename TTraits::RealType, typename TTraits::ScalarRealType, typename TTraits::FloatType, decltype(Lvalue< T >()=TTraits::NonpositiveMin(Lvalue< const T >())), decltype(Lvalue< T >()=TTraits::ZeroValue(Lvalue< const T >())), decltype(Lvalue< T >()=TTraits::OneValue(Lvalue< const T >())), RequireBoolean< decltype(TTraits::IsPositive(Lvalue< const T >()))>, RequireBoolean< decltype(TTraits::IsNonpositive(Lvalue< const T >()))>, RequireBoolean< decltype(TTraits::IsNegative(Lvalue< const T >()))>, RequireBoolean< decltype(TTraits::IsNonnegative(Lvalue< const T >()))> > NumericTraitsMembers
decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >()[Lvalue< const T2 >()])) Bracket
decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >()/Lvalue< const T2 >())) Division
std::void_t< decltype(Lvalue< T >()++), decltype(Lvalue< T >() --), decltype(++Lvalue< T >()), decltype(--Lvalue< T >())> IncrementDecrement
decltype(static_cast< T2 >(Lvalue< T1 >())) StaticCast
std::void_t< decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >() &Lvalue< const T2 >())), decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >()|Lvalue< const T2 >())), decltype(Lvalue< T3 >()=static_cast< T3 >(Lvalue< const T1 >() ^ Lvalue< const T2 >())), decltype(Lvalue< T3 >() &=static_cast< T3 >(Lvalue< const T2 >())), decltype(Lvalue< T3 >()|=static_cast< T3 >(Lvalue< const T2 >())), decltype(Lvalue< T3 >() ^=static_cast< T3 >(Lvalue< const T2 >()))> Bitwise
std::enable_if_t< std::is_convertible_v< TBoolean, bool > > RequireBoolean
decltype(Lvalue< T2 >() *=Lvalue< const T1 >()) MultiplyAndAssign
std::void_t< RequireBoolean< decltype(Lvalue< T1 >()==Lvalue< T2 >())>, RequireBoolean< decltype(Lvalue< T1 >() !=Lvalue< T2 >())> > Equality
typename T::ValueType ValueTypeMember
decltype(Lvalue< T2 >()/=Lvalue< const T1 >()) DivisionAndAssign
std::void_t< RequireBoolean< decltype(Lvalue< T1 >()< Lvalue< T2 >())>, RequireBoolean< decltype(Lvalue< T1 >()<=Lvalue< T2 >())> > LessThan
typename JoinTraits< T1, T2 >::ValueType JoinTraitsMember
constexpr bool IsValidExpression
std::void_t< RequireBoolean< decltype(Lvalue< T1 >() > Lvalue< T2 >())>, RequireBoolean< decltype(Lvalue< T1 >() >=Lvalue< T2 >())> > GreaterThan
constexpr bool IsPrimaryNumericTraits
STL namespace.