// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause // Funded by CEA, DAM, DIF, F-91297 Arpajon, France #ifndef vtkImplicitArrayTraits_h #define vtkImplicitArrayTraits_h #include "vtkSystemIncludes.h" #include #include /** * This file contains the traits for the implicit array mechanism in VTK. These traits are very much * an internal to vtkImplicitArrays and normal developers looking to develop a new vtkImplicitArray * should (ideally) not have to open this file. * * In order to ensure that template parameters passed to the vtkImplicitArray share a common * interface without having to subclass all of them from the same abstract class, we have decided to * use a trait mechanism to statically dispatch the functionalities of types passed as template * parameters to the array. * * There is 1 mandatory traits that a template type to vtkImplicitArray must implement: * - has_map_trait || is_closure_trait: ensures an implementation of int -> value * * Potential improvements to implicit arrays which would allow for write access would include the * following 2 optional traits: * - has_insert_trait || is_reference_closure_trait: provides an implementation to update the * internals of the template type to add or set new values to the array * - has_remove_trait: provides an implementation to update the internals of the template to remove * values from the array * * All the traits defining the behavior of the implicit "function" or "backend" to the * vtkImplicitArray should be composited into the implicit_array_traits */ namespace vtk { namespace detail { VTK_ABI_NAMESPACE_BEGIN template struct make_void { using type = void; }; template using void_t = typename make_void::type; ///@{ /** * \struct has_map_trait * \brief used to check whether the template type has a method named map */ template struct has_map_trait : std::false_type { }; template struct has_map_trait::type::map)>> : public has_map_trait::type::map)> { using type = T; }; template struct has_map_trait : public has_map_trait { }; template struct has_map_trait : public has_map_trait { }; template struct has_map_trait : public has_map_trait { }; template struct has_map_trait { static_assert(std::is_integral::value, "Argument to map must be integral type"); static constexpr bool value = true; using rtype = R; }; ///@} ///@{ /** * \struct is_closure_trait * \brief A trait determining whether an object acts like a mono-variable integer closure */ template struct is_closure_trait : std::false_type { }; template struct is_closure_trait> : public is_closure_trait { using type = Closure; }; template struct is_closure_trait : public is_closure_trait { }; template struct is_closure_trait : public is_closure_trait { }; template struct is_closure_trait : public is_closure_trait { }; template struct is_closure_trait : public is_closure_trait { }; template struct is_closure_trait : public is_closure_trait { }; template struct is_closure_trait { static_assert(std::is_integral::value, "Argument to closure must be integral type"); static constexpr bool value = true; using rtype = R; }; ///@} ///@{ /** * \struct has_map_tuple_trait * \brief used to check whether the template type has a method named mapTuple */ template struct has_map_tuple_trait : std::false_type { }; template struct has_map_tuple_trait::type::mapTuple)>> : public has_map_tuple_trait::type::mapTuple)> { using type = T; }; template struct has_map_tuple_trait : public has_map_tuple_trait { }; template struct has_map_tuple_trait : public has_map_tuple_trait { }; template struct has_map_tuple_trait : public has_map_tuple_trait { }; template struct has_map_tuple_trait { static_assert(std::is_integral::value, "Argument to mapTuple must be integral type"); static constexpr bool value = true; using rtype = ArgTup; }; ///@} ///@{ /** * \struct has_map_component_trait * \brief used to check whether the template type has a method named mapComponent */ template struct has_map_component_trait : std::false_type { }; template struct has_map_component_trait::type::mapComponent)>> : public has_map_component_trait::type::mapComponent)> { using type = T; }; template struct has_map_component_trait : public has_map_component_trait { }; template struct has_map_component_trait : public has_map_component_trait { }; template struct has_map_component_trait : public has_map_component_trait { }; template struct has_map_component_trait { static_assert( std::is_integral::value, "1st Argument to mapComponent must be integral type"); static_assert( std::is_integral::value, "2nd Argument to mapComponent must be integral type"); static constexpr bool value = true; using rtype = R; }; ///@} namespace iarrays { /** * \enum ReadOperatorCodes * \brief An enum for formalizing the different trait types accepted for defining a "readable" * object */ enum ReadOperatorCodes { NONE, MAP, CLOSURE }; } ///@{ /** * \struct can_map_trait * \brief An intermediate trait for exposing a unified trait interface */ template struct can_map_trait { using type = T; static constexpr bool value = false; using rtype = void; static constexpr iarrays::ReadOperatorCodes code = iarrays::NONE; }; template struct can_map_trait::rtype>> { using type = T; static constexpr bool value = true; using rtype = typename has_map_trait::rtype; static constexpr iarrays::ReadOperatorCodes code = iarrays::MAP; }; ///@} ///@{ /** * \struct can_close_trait * \brief An intermediate trait for exposing a unified trait interface */ template struct can_close_trait { using type = T; static constexpr bool value = false; using rtype = void; static constexpr iarrays::ReadOperatorCodes code = iarrays::NONE; }; template struct can_close_trait::rtype>> { using type = T; static constexpr bool value = true; using rtype = typename is_closure_trait::rtype; static constexpr iarrays::ReadOperatorCodes code = iarrays::CLOSURE; }; ///@} ///@{ /** * \struct can_map_tuple_trait * \brief An intermediate trait for exposing a unified trait interface */ template struct can_map_tuple_trait { using type = T; static constexpr bool value = false; using rtype = void; }; template struct can_map_tuple_trait::rtype>> { using type = T; static constexpr bool value = true; using rtype = typename has_map_tuple_trait::rtype; }; ///@} ///@{ /** * \struct can_map_component_trait * \brief An intermediate trait for exposing a unified trait interface */ template struct can_map_component_trait { using type = T; static constexpr bool value = false; using rtype = void; }; template struct can_map_component_trait::rtype>> { using type = T; static constexpr bool value = true; using rtype = typename has_map_component_trait::rtype; }; ///@} ///@{ /** * \struct can_get_memory_size_trait * \brief used to check whether the template type has a method named getMemorySize */ template struct can_get_memory_size_trait : std::false_type { }; template struct can_get_memory_size_trait::type::getMemorySize)>> : public can_get_memory_size_trait::type::getMemorySize)> { using type = T; static constexpr bool value = true; }; template struct can_get_memory_size_trait : public can_get_memory_size_trait { }; template struct can_get_memory_size_trait : public can_get_memory_size_trait { }; ///@} /** * \struct implicit_array_traits * \brief A composite trait for handling all the different capabilities a "backend" to an * implicit array can have */ template struct implicit_array_traits { using type = T; using trait = typename std::conditional::value, can_map_trait, can_close_trait>::type; static constexpr bool can_read = trait::value; using rtype = typename trait::rtype; static constexpr iarrays::ReadOperatorCodes code = trait::code; static constexpr bool default_constructible = std::is_default_constructible::value; static constexpr bool can_direct_read_tuple = can_map_tuple_trait::value; static constexpr bool can_direct_read_component = can_map_component_trait::value; static constexpr bool can_get_memory_size = can_get_memory_size_trait::value; }; VTK_ABI_NAMESPACE_END } // detail } // vtk #endif // vtkImplicitArrayTraits_h