Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are enum values allowed in a std::integer_sequence?

This code compiles and executes fine using GCC 13 and Clang 17, but fails to compile on MSVC. I am wondering if the code is required to work according to the standard or if this is a problem with MSVC. Demo

#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 gives this error:

error C2338: static_assert failed: 'integer_sequence<T, I...> requires T to be an integral type.'

like image 745
jtl313 Avatar asked Nov 17 '25 03:11

jtl313


2 Answers

Update:

I submitted PR 112473 and this has been fixed in GCC-trunk.


MSVC-STL and libc++† are right, as e is not an integral type (i.e. std::is_integral_v<e> is false).

From [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 is an integer type.

It is worth noting that, in contrast, integral_constant has no requirement for T, so things like integral_constant<pair<int, int>, pair{0, 0}> are perfectly fine in C++20.


† Clang's libc++ needs to be enabled through the -stdlib=libc++ flag, and it also has a corresponding static_assert in the integer_sequence implementation.

like image 171
康桓瑋 Avatar answered Nov 18 '25 17:11

康桓瑋


Clang and gcc are wrong in accepting the program as e is not an integer type(static_assert(std::is_integral_v<e>) will fail) and the first template argument for std::integer_sequence must be an integer type.

From std::integer_sequence

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

Template parameters T - an integer type to use for the elements of the sequence

And from integer type

The types char, wchar_t, char8_t, char16_t, and char32_t are collectively called character types. The character types, bool, the signed and unsigned integer types, and cv-qualified versions ([basic.type.qualifier]) thereof, are collectively termed integral types. A synonym for integral type is integer type.


You can also check this by using a static_assert:

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

Workaround

You can use std::underlying_type:

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

Demo with std::underlying_type_t

like image 45
Anoop Rana Avatar answered Nov 18 '25 16:11

Anoop Rana



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!