12#ifndef vtkKeysTraits_h
13#define vtkKeysTraits_h
15#include "vtkABINamespace.h"
25VTK_ABI_NAMESPACE_BEGIN
26template <
typename TKey,
typename TElementId,
typename TKeyId>
32VTK_ABI_NAMESPACE_BEGIN
37template <
typename In,
typename =
void>
44 std::is_integral_v<std::decay_t<decltype(std::declval<const In&>().GetNumberOfRecords())>>>>
51using RecordIdOf = std::decay_t<decltype(std::declval<const In&>().GetNumberOfRecords())>;
55template <
typename In,
typename =
void>
62 std::void_t<decltype(std::declval<const In&>().GetKey(std::declval<RecordIdOf<In>>()))>>
65 std::decay_t<decltype(std::declval<const In&>().GetKey(std::declval<
RecordIdOf<In>>()))>;
67template <
typename In,
typename =
void>
74 using type =
typename In::KeyType;
79template <
typename In,
typename =
void>
89template <
typename In,
typename =
void>
96 using type =
typename In::ElementIdType;
103using ElementKeyOf = std::decay_t<decltype(std::declval<const T&>().GetKey())>;
112template <
typename In,
typename ElementId,
typename =
void>
116template <
typename In,
typename ElementId>
118 std::void_t<decltype(std::declval<const In&>().CountElements(std::declval<RecordIdOf<In>>(),
119 std::declval<RecordIdOf<In>>(), std::declval<ElementId*>()))>> : std::true_type
124template <
typename InputMapper>
129 static_assert(isMapper,
130 "CountElements() requires an InputMapper: using ElementIdType, RecordIdType "
131 "GetNumberOfRecords() const, void CountElements(RecordIdType beginRecord, RecordIdType "
132 "endRecord, ElementIdType* counts) const");
137template <
typename Out,
typename ElementId,
typename Void,
typename... Values>
141template <
typename Out,
typename ElementId,
typename... Values>
143 std::void_t<decltype(std::declval<Out&>().SetElement(
144 std::declval<ElementId>(), std::declval<Values>()...))>,
145 Values...> : std::true_type
148template <
typename Out,
typename ElementId,
typename... Values>
152template <
typename Output,
typename ElementIdType,
typename... Values>
155 constexpr bool hasSetElement =
HasSetElement<Output, ElementIdType, Values...>::value;
156 static_assert(hasSetElement,
157 "Output must implement: SetElement(ElementIdType position, RecordIdType record) for an "
158 "Input, or SetElement(ElementIdType position, RecordIdType record, ElementIdType index) for "
160 return hasSetElement;
164template <
typename In,
typename Key,
typename =
void>
168template <
typename In,
typename Key>
170 std::enable_if_t<std::is_convertible_v<
171 decltype(std::declval<const In&>().GetKey(std::declval<RecordIdOf<In>>())), Key>>>
177template <
typename In,
typename ElementId,
typename Key,
typename =
void>
181template <
typename In,
typename ElementId,
typename Key>
183 std::void_t<decltype(std::declval<const In&>().WriteKeys(std::declval<RecordIdOf<In>>(),
184 std::declval<RecordIdOf<In>>(), std::declval<const ElementId*>(), std::declval<Key*>()))>>
190template <
typename Out,
typename ElementId,
typename =
void>
194template <
typename Out,
typename ElementId>
196 std::void_t<decltype(std::declval<Out&>().SetNumberOfElements(std::declval<ElementId>()))>>
202template <
typename Input,
typename Output>
208 static_assert(hasRecords,
"Input must implement: RecordIdType GetNumberOfRecords() const");
209 if constexpr (hasRecords)
211 constexpr bool hasTypes = !std::is_void_v<KeyType> && std::is_integral_v<ElementIdType>;
212 static_assert(hasTypes,
213 "Input must implement KeyType GetKey(RecordIdType record) const (Input), or declare a "
214 "KeyType and an integer ElementIdType (InputMapper)");
215 if constexpr (hasTypes)
219 static_assert(isInput || isMapper,
220 "Input must implement KeyType GetKey(RecordIdType record) const (Input), or void "
221 "CountElements(RecordIdType beginRecord, RecordIdType endRecord, ElementIdType* counts) "
222 "const (InputMapper)");
223 static_assert(!(isInput && isMapper),
"Input is both an Input and an InputMapper");
225 static_assert(hasWriteKeys,
226 "InputMapper must implement: void WriteKeys(RecordIdType beginRecord, RecordIdType "
227 "endRecord, const ElementIdType* offsets, KeyType* keys) const");
230 hasSize,
"Output must implement: void SetNumberOfElements(ElementIdType numberOfElements)");
231 return isInput != isMapper && hasWriteKeys && hasSize;
238template <
typename KeyType>
241 constexpr bool isKey = std::is_integral_v<KeyType> && !std::is_same_v<KeyType, bool>;
243 isKey,
"The keys of ScatterDense() must be integers: use ScatterSparse() otherwise");
248template <
typename Element,
typename ElementIdType>
252 std::is_integral_v<ElementIdType>,
"The number of elements must be of an integer type");
253 static_assert(std::is_copy_assignable_v<Element>,
"The elements must be copy assignable");
254 return std::is_integral_v<ElementIdType> && std::is_copy_assignable_v<Element>;
258template <
typename T,
typename =
void>
265 std::is_convertible_v<decltype(std::declval<const T&>() < std::declval<const T&>()), bool>>>
271template <
typename KeyType>
275 std::is_copy_assignable_v<KeyType>;
277 "The keys of ScatterSparse() must be default constructible, copy assignable, and implement "
283template <
typename P,
typename =
void>
288struct HasInitialize<P,
std::void_t<decltype(std::declval<P&>().Initialize())>> : std::true_type
292template <
typename P,
typename =
void>
297struct HasReduce<P,
std::void_t<decltype(std::declval<P&>().Reduce())>> : std::true_type
302template <
typename TKey,
typename TElementId,
typename TKeyId>
309template <
typename Keys>
313 "The keys must be DenseKeys or SparseKeys, as returned by ScatterDense() or ScatterSparse()");
318template <
typename Functor,
typename Output,
typename Keys,
typename... Args>
321 constexpr bool isFunctor = std::is_invocable_v<Functor&, Output&,
typename Keys::KeyIdType,
322 typename Keys::KeyIdType,
const typename Keys::ElementIdType*, Args...>;
323 static_assert(isFunctor,
324 "The functor of ForEachKeyRange() must implement: operator()(Output& output, KeyIdType "
325 "beginKeyId, KeyIdType "
326 "endKeyId, const ElementIdType* offsets, args...)");
331template <
typename Functor,
typename Output,
typename Keys>
334 constexpr bool isFunctor = std::is_invocable_v<Functor&, Output&,
typename Keys::KeyIdType,
335 typename Keys::KeyIdType,
const typename Keys::ElementIdType*,
typename Keys::ElementIdType*>;
336 static_assert(isFunctor,
337 "The reduce functor of Reduce() must implement: void operator()(Output& output, KeyIdType "
338 "beginKeyId, KeyIdType endKeyId, const ElementIdType* offsets, ElementIdType* counts)");
343template <
typename Out,
typename ElementId,
typename =
void>
347template <
typename Out,
typename ElementId>
349 std::void_t<decltype(std::declval<Out&>().CopyData(std::declval<const Out&>(),
350 std::declval<ElementId>(), std::declval<ElementId>(), std::declval<ElementId>()))>>
356template <
typename Output,
typename ElementIdType>
361 static_assert(isOutput,
362 "The Output of Compact() must implement: void SetNumberOfElements(ElementIdType), and void "
363 "CopyData(const Output& source, ElementIdType destinationStart, ElementIdType count, "
364 "ElementIdType sourceStart)");
369template <
typename T,
typename =
void>
376 std::is_convertible_v<decltype(std::declval<const T&>() == std::declval<const T&>()), bool>>>
382template <
typename Element>
386 static_assert(isElement,
"The elements of SortUnique must implement: operator< and operator==");
391template <
typename Functor,
typename Output,
typename Keys>
394 constexpr bool isFunctor = std::is_invocable_v<Functor&, Output&,
typename Keys::KeyIdType,
395 typename Keys::KeyIdType,
const typename Keys::ElementIdType*, uint8_t*>;
396 static_assert(isFunctor,
397 "The group functor of Group() must implement: void operator()(Output& output, KeyIdType "
398 "beginKeyId, KeyIdType endKeyId, const ElementIdType* offsets, uint8_t* groupStarts)");
403template <
typename T,
typename =
void>
410 std::is_convertible_v<decltype(std::declval<const T&>() != std::declval<const T&>()), bool>>>
416template <
typename Element>
420 static_assert(isElement,
"The elements of SortGroup must implement: operator< and operator!=");
What DenseKeys and SparseKeys share, and all that Reduce(), Group(), Compact() and ForEachKeyRange() ...
decltype(IsKeysImpl(std::declval< const T * >())) IsKeys
constexpr bool ValidateKeyRangeFunctor()
std::true_type IsKeysImpl(const KeysBase< TKey, TElementId, TKeyId > *)
constexpr bool ValidateCompactOutput()
constexpr bool ValidateReduceFunctor()
constexpr bool ValidateScatter()
typename ElementIdTypeOf< In >::type ElementIdTypeOfT
HasSetElementImpl< Out, ElementId, void, Values... > HasSetElement
constexpr bool ValidateSparseKey()
std::decay_t< decltype(std::declval< const T & >().GetKey())> ElementKeyOf
constexpr bool ValidateCountElements()
constexpr bool ValidateSortGroup()
std::decay_t< decltype(std::declval< const In & >().GetNumberOfRecords())> RecordIdOf
constexpr bool ValidateSetElement()
constexpr bool ValidateArray()
constexpr bool ValidateDenseKey()
typename KeyTypeOf< In >::type KeyTypeOfT
constexpr bool ValidateKeys()
constexpr bool ValidateGroupFunctor()
constexpr bool ValidateSortUnique()
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
typename In::ElementIdType type
std::decay_t< decltype(std::declval< const In & >().GetKey(std::declval< RecordIdOf< In > >()))> type
typename In::KeyType type