diff --git a/vtkm/testing/UnitTestTuple.cxx b/vtkm/testing/UnitTestTuple.cxx index 87d78ada3..6ff4a71f8 100644 --- a/vtkm/testing/UnitTestTuple.cxx +++ b/vtkm/testing/UnitTestTuple.cxx @@ -10,11 +10,159 @@ #include +#include + #include namespace { +// Do some compile-time testing of vtkmstd::integer_sequence. This is only tangentially +// related to Tuple, but the two are often used together. +template +using SequenceId = vtkmstd::integer_sequence; + +template +using MakeSequenceId = vtkmstd::make_integer_sequence; + +VTKM_STATIC_ASSERT((std::is_same, SequenceId<>>::value)); +VTKM_STATIC_ASSERT((std::is_same, SequenceId<0>>::value)); +VTKM_STATIC_ASSERT((std::is_same, SequenceId<0, 1>>::value)); +VTKM_STATIC_ASSERT((std::is_same, SequenceId<0, 1, 2>>::value)); +VTKM_STATIC_ASSERT((std::is_same, SequenceId<0, 1, 2, 3, 4>>::value)); +VTKM_STATIC_ASSERT((std::is_same, SequenceId<0, 1, 2, 3, 4, 5, 6, 7>>::value)); +VTKM_STATIC_ASSERT( + (std::is_same, SequenceId<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>>::value)); +VTKM_STATIC_ASSERT( + (std::is_same< + MakeSequenceId<21>, + SequenceId<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20>>::value)); +VTKM_STATIC_ASSERT((std::is_same, + SequenceId<0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33>>::value)); +VTKM_STATIC_ASSERT((std::is_same, + SequenceId<0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88>>::value)); + template struct TypePlaceholder { diff --git a/vtkmstd/CMakeLists.txt b/vtkmstd/CMakeLists.txt index 01f48f3ac..6cde8bc0b 100644 --- a/vtkmstd/CMakeLists.txt +++ b/vtkmstd/CMakeLists.txt @@ -10,6 +10,7 @@ set(headers aligned_union.h + integer_sequence.h is_trivially_copyable.h void_t.h ) diff --git a/vtkmstd/integer_sequence.h b/vtkmstd/integer_sequence.h new file mode 100644 index 000000000..d78ed15c3 --- /dev/null +++ b/vtkmstd/integer_sequence.h @@ -0,0 +1,234 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_std_integer_sequence_h +#define vtk_m_std_integer_sequence_h + +#include + +#include + +#include + +#if defined(__cpp_lib_integer_sequence) +#define VTK_M_USE_STD_INTEGER_SEQUENCE +#elif (__cplusplus >= 201402L) +#define VTK_M_USE_STD_INTEGER_SEQUENCE +#elif defined(VTKM_MSVC) +#define VTK_M_USE_STD_INTEGER_SEQUENCE +#endif + +#if (__cplusplus >= 201402L) +#define VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE +#elif defined(VTKM_MSVC) && (_MSC_FULL_VER >= 190023918) +#define VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE +#endif + +namespace vtkmstd +{ + +#ifndef VTK_M_USE_STD_INTEGER_SEQUENCE + +template +struct integer_sequence +{ + using value_type = T; + + static constexpr std::size_t size() noexcept { return sizeof...(Ns); } +}; + +template +using index_sequence = integer_sequence; + +#else // VTK_M_USE_STD_INTEGER_SEQUENCE + +using std::integer_sequence; +using std::index_sequence; + +#endif // VTK_M_USE_STD_INTEGER_SEQUENCE + +#ifndef VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE + +namespace detail +{ + +// Implementation note: ideally these implementation classes would define "Num" +// as the type for the sequence (i.e. T). However, compilers have trouble +// resolving template partial specialization for a number whose type is one of +// the other template parameters. (Most compilers allow you to specify them in +// an integral_constant, but versions of GCC fail at that, too.) Instead, we are +// using std::size_t for the num, which should be large enough. +using SeqSizeT = std::size_t; + +template +struct MakeSequenceImpl; + +template +struct DoubleSequence; + +template +struct DoubleSequence> +{ + using type = vtkmstd::integer_sequence; +}; + +template +struct CombineSequences; + +template +struct CombineSequences, vtkmstd::integer_sequence> +{ + using type = vtkmstd::integer_sequence; +}; + +template +struct ExpandSequence; + +template +struct ExpandSequence> +{ + static constexpr SeqSizeT OldSize = sizeof...(Ns); + static constexpr SeqSizeT RemainingAfter = Num - OldSize; + static constexpr bool CanDoubleNext = RemainingAfter >= OldSize * 2; + using type = typename ExpandSequence< + CanDoubleNext, + RemainingAfter, + typename DoubleSequence>::type>::type; +}; + +template +struct ExpandSequence> +{ + using type = typename CombineSequences, + typename MakeSequenceImpl::type>::type; +}; + +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; + +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; +template +struct MakeSequenceImpl +{ + using type = vtkmstd::integer_sequence; +}; + +template +struct MakeSequenceImpl +{ + VTKM_STATIC_ASSERT(Num >= 16); + VTKM_STATIC_ASSERT_MSG(Num < (1 << 20), "Making an unexpectedly long integer sequence."); + using type = + typename ExpandSequence<(Num >= 32), Num - 16, typename MakeSequenceImpl::type>::type; +}; + +} // namespace detail + +template +using make_integer_sequence = + typename detail::MakeSequenceImpl(N)>::type; + +template +using make_index_sequence = make_integer_sequence; + +#else // VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE + +using std::make_integer_sequence; +using std::make_index_sequence; + +#endif // VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE + +} // namespace vtkmstd + +#ifdef VTK_M_USE_STD_INTEGER_SEQUENCE +#undef VTK_M_USE_STD_INTEGER_SEQUENCE +#endif + +#ifdef VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE +#undef VTK_M_USE_STD_MAKE_INTEGER_SEQUENCE +#endif + +#endif //vtk_m_std_integer_sequence_h