std::integer_sequence 中是否允许枚举值?

jtl*_*313 22 c++ language-lawyer c++14

此代码使用 GCC 13 和 Clang 17 可以正常编译和执行,但无法在 MSVC 上编译。我想知道代码是否需要按照标准工作,或者这是否是 MSVC 的问题。 演示

#include <utility>
#include <iostream>

enum e : int { A=5, B, C, D };

auto x = std::integer_sequence<e, A, B, C, D>{};
auto y = std::integer_sequence<unsigned, 9, 4, 3, 8>{};
auto z = std::integer_sequence<int, 0, 1, 2, 3>{};

template<typename T, T... ints>
void print_sequence(std::integer_sequence<T, ints...> int_seq)
{
    std::cout << "The sequence of size " << int_seq.size() << ": ";
    ((std::cout << ints << ' '), ...);
    std::cout << '\n';
}

int main(int, char**)
{
    print_sequence(x);
    print_sequence(y);
    print_sequence(z);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

MSVC 给出这个错误:

错误 C2338:static_assert 失败:“integer_sequence<T, I...> 要求 T 为整数类型。”

康桓瑋*_*康桓瑋 18

更新:

\n

我提交了PR 112473,该问题已在 GCC-trunk 中修复。

\n
\n

MSVC-STL 和 libc++\xe2\x80\xa0 是正确的,因为e不是整型(即std::is_integral_v<e>false

\n

来自[intseq.intseq]

\n
\n
namespace std {\n  template<class T, T... I> struct integer_sequence {\n    using value_type = T;\n    static constexpr size_t size() noexcept { return sizeof...(I); }\n  };\n}\n
Run Code Online (Sandbox Code Playgroud)\n

MandatesT是一个整数类型。

\n
\n

值得注意的是,相比之下,integral_constant对 没有要求T,因此类似的事情integral_constant<pair<int, int>, pair{0, 0}>在 C++20 中完全没问题。

\n
\n

\xe2\x80\xa0 Clang的libc++需要通过flag来启用,在实现中-stdlib=libc++也有对应的static_assertinteger_sequence

\n

  • @Red.Wave 什么是STL?标准中没有提及它(除了作为“明显*”一词的一部分)。无论如何,如果您认为这很容易,请提交提案。确保参加委员会会议,向其他委员会成员解释这一点,并针对不可避免的“我们为什么需要它”和“它可能会破坏向后兼容性”等问题进行辩护。 (2认同)

use*_*570 14

Clang 和 gcc 在接受程序时是错误的,因为e不是整数类型(static_assert(std::is_integral_v<e>)会失败),并且 的第一个模板参数std::integer_sequence必须是整数类型。

来自std::integer_sequence

template< class T, T... Ints >
class integer_sequence;   (since C++14)
Run Code Online (Sandbox Code Playgroud)

模板参数 T - 用于序列元素的整数类型

并且来自整数类型

char、wchar_t、char8_t、char16_t 和 char32_t 类型统称为字符类型。字符类型 bool、有符号和无符号整数类型及其 cv 限定版本 ([basic.type.qualifier]) 统称为整数类型。整型的同义词是整型。


您还可以使用 static_assert 来检查这一点:

static_assert(std::is_integral_v<e>); //msvc, gcc and clang all fail this as expected
Run Code Online (Sandbox Code Playgroud)

解决方法

您可以使用std::underlying_type

auto x = std::integer_sequence<std::underlying_type_t<e>, A, B, C, D>{};
Run Code Online (Sandbox Code Playgroud)

使用 std::underlying_type_t 进行演示