The C++ Standard Requires Proprietary Language Extensions

The C++ standard consists of two parts. The language and the library. The latter is built upon the first, or so I thought.

It starts with a fairly common pattern …

I have a couple of (strongly typed) enums, e.g:

enum class EFoo { FOO0, FOO1 };
enum class EBar : size_t { BAR0, BAR1 };

Define EFoo and EBar

Occasionally I’d like to print the symbolic name of an enum, so I made it a habit to create an array of character arrays.

char const * const EFooStr[]{"FOO0", "FOO1"};
char const * const EBarStr[]{"BAR0", "BAR1"};

Symbolic names for enums

This allows me to print them, use them in exception messages, verbose output etc.:

EFooStr[static_cast<int>(EFoo::FOO0)];

Use an enum as an array index to retrieve a character array

There are other legitimate uses of casting an enum to its value type, including returning the value from the main function, and when using pre-C++11 or C interfaces.

Because writing static_cast<TYPE>(ENUM) becomes annoying and requires looking up the value type I started to define an overload for to_value() for each enum class:

constexpr int to_value(EFoo const op) {
	return static_cast<int>(op);
}
constexpr size_t to_value(EBar const op) {
	return static_cast<size_t>(op);
}

Define a to_value() overload for each enum class

This makes the lookup less verbose without hiding that type cast/conversion is happening:

EFooStr[to_value(EFoo::FOO0)];

A less annoying way of casting an enum to the underlying value type

Simplifying

However adding an overload for each enum seems excessive and redundant to me, so I tried to use my imagination to come up with a function template that works for all enums:

template <class ET, typename VT>
constexpr VT to_value(ET : VT const op) {
	return static_cast<VT>(op);
}

My best idea (not legal C++ code!)

Unfortunately this isn’t legal C++ code in C++11 or C++14. However there is a way of doing it, after failing I googled the problem and came up with the std::underlying_type trait:

#include <type_traits>
template <class ET, typename VT = typename std::underlying_type<ET>::type>
constexpr VT to_value(ET const op) {
	return static_cast<VT>(op);
}

Using a meta function to extract the underlying value type

After failing to come up with my own solution I had thought a meta function like that would be impossible, but clearly I was wrong. I spent another hour trying to come up with a meta programming trick to implement my own underlying_type meta function until I gave up and looked it up in the code of the standard library.

It turned out, the library cheats:

template <class _Tp>
struct underlying_type
{
    typedef _LIBCPP_UNDERLYING_TYPE(_Tp) type;
};

No meta programming here

The meta function is just a wrapper around a proprietary compiler feature (Clang Language Extenstions):

  • __underlying_type(type): Retrieves the underlying type for a given enum type. This trait is required to implement the C++11 standard library.

Conclusion

So the standard provides a way of accessing the underlying type of a strongly typed enum through the library, but the language does not provide a way to implement the library.

This is not really a problem, but it’s certainly undesirable.