mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
Add vtkmstd::integer_sequence
`integer_sequence` is an essential tool when dealing with structures like a `Tuple`. Make sure that we have one (even though it was not introduced until C++14).
This commit is contained in:
parent
5773ea3e13
commit
dca8144345
@ -10,11 +10,159 @@
|
||||
|
||||
#include <vtkm/Tuple.h>
|
||||
|
||||
#include <vtkmstd/integer_sequence.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
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 <vtkm::IdComponent... Ns>
|
||||
using SequenceId = vtkmstd::integer_sequence<vtkm::IdComponent, Ns...>;
|
||||
|
||||
template <vtkm::IdComponent N>
|
||||
using MakeSequenceId = vtkmstd::make_integer_sequence<vtkm::IdComponent, N>;
|
||||
|
||||
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<0>, SequenceId<>>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<1>, SequenceId<0>>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<2>, SequenceId<0, 1>>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<3>, SequenceId<0, 1, 2>>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<5>, SequenceId<0, 1, 2, 3, 4>>::value));
|
||||
VTKM_STATIC_ASSERT((std::is_same<MakeSequenceId<8>, SequenceId<0, 1, 2, 3, 4, 5, 6, 7>>::value));
|
||||
VTKM_STATIC_ASSERT(
|
||||
(std::is_same<MakeSequenceId<13>, 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<MakeSequenceId<34>,
|
||||
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<MakeSequenceId<89>,
|
||||
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 <vtkm::IdComponent Index>
|
||||
struct TypePlaceholder
|
||||
{
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
set(headers
|
||||
aligned_union.h
|
||||
integer_sequence.h
|
||||
is_trivially_copyable.h
|
||||
void_t.h
|
||||
)
|
||||
|
234
vtkmstd/integer_sequence.h
Normal file
234
vtkmstd/integer_sequence.h
Normal file
@ -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 <vtkm/internal/Configure.h>
|
||||
|
||||
#include <vtkm/StaticAssert.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#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 <typename T, T... Ns>
|
||||
struct integer_sequence
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
static constexpr std::size_t size() noexcept { return sizeof...(Ns); }
|
||||
};
|
||||
|
||||
template <std::size_t... Ns>
|
||||
using index_sequence = integer_sequence<std::size_t, Ns...>;
|
||||
|
||||
#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 <typename T, SeqSizeT Num>
|
||||
struct MakeSequenceImpl;
|
||||
|
||||
template <typename Sequence>
|
||||
struct DoubleSequence;
|
||||
|
||||
template <typename T, T... Ns>
|
||||
struct DoubleSequence<vtkmstd::integer_sequence<T, Ns...>>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, Ns..., T(sizeof...(Ns)) + Ns...>;
|
||||
};
|
||||
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
struct CombineSequences;
|
||||
|
||||
template <typename T, T... N1s, T... N2s>
|
||||
struct CombineSequences<vtkmstd::integer_sequence<T, N1s...>, vtkmstd::integer_sequence<T, N2s...>>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, N1s..., T(sizeof...(N1s)) + N2s...>;
|
||||
};
|
||||
|
||||
template <bool CanDouble, SeqSizeT Num, typename Sequence>
|
||||
struct ExpandSequence;
|
||||
|
||||
template <typename T, SeqSizeT Num, T... Ns>
|
||||
struct ExpandSequence<true, Num, vtkmstd::integer_sequence<T, Ns...>>
|
||||
{
|
||||
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<vtkmstd::integer_sequence<T, Ns...>>::type>::type;
|
||||
};
|
||||
|
||||
template <typename T, SeqSizeT Num, T... Ns>
|
||||
struct ExpandSequence<false, Num, vtkmstd::integer_sequence<T, Ns...>>
|
||||
{
|
||||
using type = typename CombineSequences<vtkmstd::integer_sequence<T, Ns...>,
|
||||
typename MakeSequenceImpl<T, Num>::type>::type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 0>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 1>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 2>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 3>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 4>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 5>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 6>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 7>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 8>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 9>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 10>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 11>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 12>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 13>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 14>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 15>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14>;
|
||||
};
|
||||
template <typename T>
|
||||
struct MakeSequenceImpl<T, 16>
|
||||
{
|
||||
using type = vtkmstd::integer_sequence<T, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>;
|
||||
};
|
||||
|
||||
template <typename T, SeqSizeT Num>
|
||||
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<T, 16>::type>::type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, T N>
|
||||
using make_integer_sequence =
|
||||
typename detail::MakeSequenceImpl<T, static_cast<detail::SeqSizeT>(N)>::type;
|
||||
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
||||
|
||||
#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
|
Loading…
Reference in New Issue
Block a user