Это не готовая реализация CTC, а только прототип, упрощенный до предела так, чтобы видна была идея.
Достоинства:
Не используются никакие константы препроцессора (__LINE__, __COUNTER__ и пр);
Не используется специализации шаблона основного класса счетчика, что допускает его применение не только в пространстве имен, но и в теле классов (до C++17 спещиализация вложенных классов должна была выполняться только в обрамляющем пространстве имен);
Возможность одновременного использования множества независимых счетчиков;
Огранченность областью видимости. Счетчики из вложенных областей видимости не конфликтуют с одноименными счетчиками из охватывающих областей видимости;
Автоматический инкремент при каждом обращении к счетчику.
Недостатки:
Ограничение максимального значения счетчика, довольно низкое. Над этим заморачиваться не нужно, решение уже найдено;
ГЛАВНАЯ ПРОБЛЕМА: привести счетчик в соответствие требованиям стандарта! Сейчас эта реализация работает только на msvc. Как я ни бился, мне так и не удалось заставить это заработать под gcc. Причина ясна — дружественная функция не появляется в окружающем пространстве имен.
http://rextester.com/ZSP64839
constexpr size_t CTC_MAX = 498;
template <size_t i>
struct Index : Index<i - 1> { static constexpr size_t value = i; };
template <> struct Index<0> { static constexpr size_t value = 0; };
Index<0> generate(...);
#define CREATE_CTC(name) \
template <typename T = decltype(generate(Index<CTC_MAX>()))> \
struct name : T \
{ \
friend Index<T::value + 1> generate(T); \
};
#define GET_CTC(name) name<>::value
Пример использования:
CREATE_CTC(ctc1)
enum class Foo
{
zero = GET_CTC(ctc1),
one = GET_CTC(ctc1),
two = GET_CTC(ctc1),
three = GET_CTC(ctc1),
four = GET_CTC(ctc1),
five = GET_CTC(ctc1),
};