如何从std :: integer_sequence初始化静态数组?

时间:2019-08-26 13:24:32

标签: c++ templates c++17 std

我为符合以下规则的枚举创建了可迭代的生成器:

  • 枚举是整数序列,没有空格
  • 给出枚举的最后一个元素不是实际的枚举元素

该类如下:

template <typename EnumType, EnumType LENGTH>
class EnumArrayNonStatic
{
public:
  using ValueType = typename std::underlying_type<EnumType>::type;
  //! Initialize values via private constructor
  constexpr EnumArrayNonStatic() : EnumArrayNonStatic(std::make_integer_sequence<ValueType, (ValueType)LENGTH>{}) {}

  //! All values generated via std::integer_sequence
  EnumType values[(int)LENGTH];
private:
  //! Private constructor that populates values
  template <int... Indices>
  constexpr EnumArrayNonStatic(std::integer_sequence<int, Indices...>) : values{(static_cast<EnumType>(Indices))...} {}
};

用法:

enum class TestEnum
{
  A,
  B,
  C,
  D,
  LENGTH
};
int main()
{
  for (const TestEnum val : EnumArrayNonStatic<TestEnum, TestEnum::LENGTH>().values)
  {
    std::cout << (int)val << "\n";
  }
  return 0;
}

但是,我希望能够使用EnumArray<TestEnum, TestEnum::LENGTH>::values并在编译期间通过模板生成值。我是这样写的:

template <typename EnumType, EnumType LENGTH>
class EnumArray
{
private:
  using ValueType = typename std::underlying_type<EnumType>::type;
  //! Static generator of value array (returns EnumType[])
  template <ValueType... Indices>
  static constexpr auto GenerateArray(std::integer_sequence<ValueType, Indices...>) { return {(static_cast<EnumType>(Indices))...}; }
public:
  //! Static array of values of an enum
  static constexpr EnumType values[static_cast<ValueType>(LENGTH)] = GenerateArray(std::make_integer_sequence<ValueType, static_cast<ValueType>(LENGTH) >{});
};

我一直在弄乱代码一段时间,但我总是不断出错。上面的版本打印:

1>enumiteratortest.cpp(22): error C3108: cannot deduce a type as an initializer list is not an expression
1>enumiteratortest.cpp(25): note: see reference to function template instantiation 'auto EnumArray<TestEnum,TestEnum::LENGTH>::GenerateArray<0,1,2,3>(std::integer_sequence<int,0,1,2,3>)' being compiled
1>enumiteratortest.cpp(52): note: see reference to class template instantiation 'EnumArray<TestEnum,TestEnum::LENGTH>' being compiled
1>enumiteratortest.cpp(22): error C2440: 'return': cannot convert from 'initializer list' to 'auto'
1>enumiteratortest.cpp(22): note: There is no context in which this conversion is possible
1>enumiteratortest.cpp(25): error C2440: 'initializing': cannot convert from 'void' to 'const EnumType [4]'
1>        with
1>        [
1>            EnumType=TestEnum
1>        ]
1>enumiteratortest.cpp(25): note: There are no conversions to array types, although there are conversions to references or pointers to arrays

肯定有一种方法可以静态地初始化数组。 GenerateArray甚至是必要的吗?有没有办法做到这一点?

int myArray[] = std::integer_sequence<ValueType, Indices...>{Indices...}

还是有些东西?

1 个答案:

答案 0 :(得分:5)

您不能使用initializer_list初始化语言数组。而且,您不能将该函数的返回类型更改为数组-函数不能返回数组。

只需将所有内容更改为std::array

template <ValueType... Indices>
static constexpr auto GenerateArray(std::integer_sequence<ValueType, Indices...>)
    -> std::array<EnumType, sizeof...(Indices)>
{
    return {(static_cast<EnumType>(Indices))...};
}

static constexpr std::array<EnumType,  static_cast<ValueType>(LENGTH)> values
      = GenerateArray(std::make_integer_sequence<ValueType, static_cast<ValueType>(LENGTH)>{});
相关问题