7

Can I define a type to use as the underlying type of an enumeration? Something like this:

struct S {
    S(int i) : value(i) {}
    operator int() { return value; }

    int value;
};

enum E : S {
    A, B, C
};

The error message tells me that S must be an integral type. I have tried to specialize std::is_integral like the following, but it seems that in this context, "integral type" really means one of the fundamental types.

namespace std {
    template<>
    struct is_integral<S> : public true_type {};
}

So, using any version of C++, is there a way to make a custom type pass off as an integral type?

Nelfeal
  • 12,593
  • 1
  • 20
  • 39

2 Answers2

3

Can I define a type to use as the underlying type of an enumeration?

You can only use integral types to define enums, not any old type.

For example, you can use

enum E : char {
    A, B, C
};

to indicate the value of E will be of type char. But you can't use

enum E : S {
    A, B, C
};

From the C++11 Standard, 3.9.1/7:

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • So the "integral type" in this context has nothing to do with `std::is_integral`? – Nelfeal Jun 18 '17 at 19:01
  • The example you posted will be a subversion of the intent of `std::is_integral`. I am not sure whether there is anything in the language to prevent that. – R Sahu Jun 18 '17 at 19:04
  • 3
    [Looks like specializing anything in `` is undefined behavior.](https://stackoverflow.com/questions/8513417/what-can-and-cant-i-specialize-in-the-std-namespace). I should have looked more thoroughly. Also [this](https://stackoverflow.com/questions/25345486/why-specializing-a-type-trait-could-result-in-undefined-behaviour) (thanks HolyBlackCat). – Nelfeal Jun 18 '17 at 19:29
2

std::is_integral checks whether T is an integral type. Provides the member constant value which is equal to true, if T is the type bool, char, char16_t, char32_t, wchar_t, short, int, long, long long, or any implementation-defined extended integer types, including any signed, unsigned, and cv-qualified variants. Otherwise, value is equal to false.

This is an excerpt from here. This means that an enum must be using one of the following types:

bool, char, char16_t, char32_t, wchar_t, short, int, long, long long.

Shiro
  • 2,610
  • 2
  • 20
  • 36
  • [That doesn't mean you can't specialize `is_integral`.](http://coliru.stacked-crooked.com/a/b9828b8eaf4d59e3) – Nelfeal Jun 18 '17 at 19:00
  • I don't believe I wrote anything contrary. – Shiro Jun 18 '17 at 19:04
  • @Nelxiost You have it backwards. `std::is_integral` indicates if a type is integral, which is defined by the standard and the implementation. Specializing things in `std::` is (usually) UB – Caleth Jun 18 '17 at 19:18
  • @Shiro Your answer lets me think that an `enum` must be using a type T for which `std::is_integral() == true`. Which is not the case. – Nelfeal Jun 18 '17 at 19:26
  • @Nelxiost https://stackoverflow.com/questions/25345486/why-specializing-a-type-trait-could-result-in-undefined-behaviour – HolyBlackCat Jun 18 '17 at 19:29