Информация об изменениях

Сообщение CTC без препроцссора - помогите довести до ума! от 13.04.2017 21:32

Изменено 13.04.2017 21:33 rg45

Re: CTC без препроцссора - помогите довести до ума!
Это не готовая реализация 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),
};
CTC без препроцссора - помогите довести до ума!
Это не готовая реализация 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),
};