So, first yes, my co-author Christian has written a reference implementation that contains a superset of the N3815 proposed three property queries. You will find the link on the bottom of N3815. This has been forked and extended by Remotion (linked previously in this thread).
But before you go diving into that and compiling custom implementation, the three traits are really simple to understand and to mock up by hand with an ordinary compiler:
First recall the three property queries are:
enumerator_list_size<E> is the number of enumerators in the enumeration E
enumerator_value<E,I> is a value of type E that is the I'th enumerator in declared order.
enumerator_identifier<E,I> is a string literal with the identifier of the I'th enumerator in declared order.
So you can mock them up for experimentation "by hand" without compiler changes as follows:
First declare but don't define the three N3815 primaries...
template<typename E> struct enumerator_list_size;
template<typename E, size_t I> struct enumerator_value;
template<typename E, size_t I> struct enumerator_identifier;
Then for each enumeration type in your test program, for example...
enum foo
{
bar,
Baz,
Qux = 42,
Quux = 42,
};
...manually define a set of specializations by hand as follows...
template<> struct enumerator_list_size<foo> { static constexpr size_t value = 4; };
template<> struct enumerator_value<foo,0> { static constexpr foo value = bar; };
template<> struct enumerator_value<foo,1> { static constexpr foo value = Baz; };
template<> struct enumerator_value<foo,2> { static constexpr foo value = Qux; };
template<> struct enumerator_value<foo,3> { static constexpr foo value = Quux; };
template<> struct enumerator_identifier<foo,0> { static constexpr char value[4] = u8"bar"; };
template<> struct enumerator_identifier<foo,1> { static constexpr char value[4] = u8"Baz"; };
template<> struct enumerator_identifier<foo,2> { static constexpr char value[4] = u8"Qux"; };
template<> struct enumerator_identifier<foo,3> { static constexpr char value[5] = u8"Quux"; };
constexpr char enumerator_identifier<foo,0>::value[];
constexpr char enumerator_identifier<foo,1>::value[];
constexpr char enumerator_identifier<foo,2>::value[];
constexpr char enumerator_identifier<foo,3>::value[];
(The effect of N3815 is that these hand-written specializations will be done automatically for you by the compiler when you use them.)
Here is a complete self-contained compiling program with the above integrated together you can copy and paste plus some tests:
#include <cassert>
#include <cstddef>
#include <string.h>
// N3815 primaries
template<typename E> struct enumerator_list_size;
template<typename E, size_t I> struct enumerator_value;
template<typename E, size_t I> struct enumerator_identifier;
// your enumeration
enum foo
{
bar,
Baz,
Qux = 42,
Quux = 42,
};
// define these specializations by hand:
template<> struct enumerator_list_size<foo> { static constexpr size_t value = 4; };
template<> struct enumerator_value<foo,0> { static constexpr foo value = bar; };
template<> struct enumerator_value<foo,1> { static constexpr foo value = Baz; };
template<> struct enumerator_value<foo,2> { static constexpr foo value = Qux; };
template<> struct enumerator_value<foo,3> { static constexpr foo value = Quux; };
template<> struct enumerator_identifier<foo,0> { static constexpr char value[4] = u8"bar"; };
template<> struct enumerator_identifier<foo,1> { static constexpr char value[4] = u8"Baz"; };
template<> struct enumerator_identifier<foo,2> { static constexpr char value[4] = u8"Qux"; };
template<> struct enumerator_identifier<foo,3> { static constexpr char value[5] = u8"Quux"; };
constexpr char enumerator_identifier<foo,0>::value[];
constexpr char enumerator_identifier<foo,1>::value[];
constexpr char enumerator_identifier<foo,2>::value[];
constexpr char enumerator_identifier<foo,3>::value[];
// test they work:
int main()
{
static_assert(enumerator_list_size<foo>::value == 4, "");
assert(strcmp(enumerator_identifier<foo,0>::value, u8"bar") == 0);
assert(strcmp(enumerator_identifier<foo,1>::value, u8"Baz") == 0);
assert(strcmp(enumerator_identifier<foo,2>::value, u8"Qux") == 0);
assert(strcmp(enumerator_identifier<foo,3>::value, u8"Quux") == 0);
static_assert(enumerator_value<foo,0>::value == bar, "");
static_assert(enumerator_value<foo,1>::value == Baz, "");
static_assert(enumerator_value<foo,2>::value == Qux, "");
static_assert(enumerator_value<foo,3>::value == Quux, "");
constexpr const char* str = enumerator_identifier<foo,0>::value;
static_assert(str[0] == 'b', "");
static_assert(str[1] == 'a', "");
static_assert(str[2] == 'r', "");
static_assert(str[3] == '\0', "");
}
Enjoy,
Andrew.