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

Are enum values allowed in a std::integer_sequence?

提问人:jtl313 提问时间:11/9/2023 最后编辑:Ch3steRjtl313 更新时间:11/10/2023 访问量:1286

问:

此代码使用 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;
}

MSVC 给出以下错误:

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

C++ C++14 语言律师

评论

0赞 user12002570 11/9/2023
简化示例。
2赞 Aconcagua 11/9/2023
旁注:你可以回退到 std::integer_sequence<std::underlying_type_t<e>,...>

答:

18赞 康桓瑋 11/9/2023 #1

更新:

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


MSVC-STL 和 libc++† 是正确的,因为它不是整数类型(即 是 )。estd::is_integral_v<e>false

来自 [intseq.intseq]

namespace std {
  template<class T, T... I> struct integer_sequence {
    using value_type = T;
    static constexpr size_t size() noexcept { return sizeof...(I); }
  };
}

Mandates:是整数类型。T

值得注意的是,相比之下,对 没有要求,所以像这样的东西在 C++20 中是完全可以的。integral_constantTintegral_constant<pair<int, int>, pair{0, 0}>


† Clang 的 libc++ 需要通过标志启用,在实现中也有对应的static_assert-stdlib=libc++integer_sequence

评论

0赞 Red.Wave 11/9/2023
@HolyBlackCat,在性病中再次出现相同的缺陷。与其说是这么长的注释,不如约束标准模板呢?放在那里:它是不言自明的,并强制执行正确的行为。template <std::integral T>
0赞 n. m. could be an AI 11/9/2023
@Red.Wave:因为他们在委员会中没有无限的人年。
1赞 Red.Wave 11/9/2023
@n.m.couldbeanAI中,要求很简单:“STL类和函数应受到概念的约束,以反映标准要求”。实施者应该加强他们的实现。许多类已经使用旧的 SFINAE adhoc;在宏中添加一个子句没什么大不了的。requiresENABLE_IF
2赞 n. m. could be an AI 11/9/2023
@Red.Wave 什么是STL?标准中没有提到它(除了作为这个词的一部分)。无论如何,如果您认为这很容易,请提交提案。确保参加委员会会议,向其他委员会成员解释它,并捍卫它免受不可避免的“我们为什么需要它”和“它可能会破坏向后兼容性”之类的话。
1赞 Red.Wave 11/9/2023
@n.m.couldbeanAI如果我能参加会议就好了,我会提到很多。
14赞 user12002570 11/9/2023 #2

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

std::integer_sequence

template< class T, T... Ints >
class integer_sequence;   (since C++14)

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

from 整数类型

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

解决方法

您可以使用 std::underlying_type

auto x = std::integer_sequence<std::underlying_type_t<e>, A, B, C, D>{};

使用 std::underlying_type_t 进行演示