Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting the types of individual enumeration constants

The code below prints unsigned int as the underlying type of all the constants inside the enum Test

#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>

struct Test 
{
    enum { a = true, b = 1 };    
};

static_assert(std::is_same<
    std::underlying_type_t<decltype(Test::a)>, 
    std::underlying_type_t<decltype(Test::b)>>::value, ""
);

int main()
{    
    int status;
    auto const& bi = typeid(std::underlying_type_t<decltype(Test::a)>);
    std::cout << abi::__cxa_demangle(bi.name(), 0, 0, &status); // unsigned int
}

Live Example. This also happens if Test contains two separate enums with a and b as before.

Question: is it possible to detect that Test::a is initialized with bool and Test::b with int? Is there any experimental code for this in any of the Reflection Study Group proposals for C++17?

NOTE: I know I can work around it by replacing Test with

struct Test
{
    static constexpr auto a = true;
    static constexpr auto b = 1;
};

but I find the enum version slightly less verbose in its usage.

like image 966
TemplateRex Avatar asked Jun 29 '14 14:06

TemplateRex


1 Answers

It is not possible and I consider it very unlikely that it will ever be possible.

The reason is that a and b are values of the (in your case unnnamed) enum. Thus they are, by definition, of the type of the enum, meaning: Of the same type. The expressions used to initialize them and their respective types are only used to "calculate" the underlying type of the enum, not of any individual values.

Considering this fact, I think that even reflection will not help to recover the information as the type of the initializing expression is abstracted away when you look at an enum's value.

What you'd need is an even deeper level of inspection where you'd need to access the expression used to initialize the values. That would mean that compilers will have to store a lot of additional information for every variable, values, etc. (since this would be a general thing not just for enums).

Consider what that means:

  • Increased compile times
  • Increased memory usage when compiling
  • Every value would effectively now have two types, the type it is declared as and the type of the expression it was initialized from

The last point is what I would consider the real catastrophe for the language. A value should have a single type, the expression used to initialized the value should not be accessible in any way. This is what abstraction is about, breaking it could lead to all kinds of subtle dependencies and a lot of complexity.

Disclaimer: This is just my personal opinion, I can't speak for anyone on the committee or in the working groups.

like image 77
Daniel Frey Avatar answered Sep 26 '22 02:09

Daniel Frey