Вот еще одна альтернативная реализация. https://stackoverflow.com/a/6174263/1190123, вероятно, лучше, но даже после ручной обработки нескольких шагов на бумаге я все еще не совсем понимаю математику / фильтрацию.
Используется рекурсия функции constexpr для подсчета количества не шаблонных объявленных функций Highest
. __COUNTER__
используется в качестве механизма генерации для предотвращения самостоятельной рекурсии новых объявлений Highest
.
Это компилируется только для меня (3.3). Я не уверен, что это соответствует, но я надеюсь. В g ++ 4.8 происходит сбой из-за нереализованной функции (согласно ошибке). Компилятор Intel 13 также не работает из-за ошибки constexpr.
256 счетчик уровня
Максимальный счетчик на счетчик равен 250 (CounterLimit). CounterLimit может быть увеличен до 256, если вы не реализуете содержимое LCount ниже.
Осуществление
#include <iostream>
#include <type_traits>
constexpr unsigned int CounterLimit = 250;
template <unsigned int ValueArg> struct TemplateInt { constexpr static unsigned int Value = ValueArg; };
template <unsigned int GetID, typename, typename TagID>
constexpr unsigned int Highest(TagID, TemplateInt<0>)
{
return 0;
}
template <unsigned int GetID, typename, typename TagID, unsigned int Index>
constexpr unsigned int Highest(TagID, TemplateInt<Index>)
{
return Highest<GetID, void>(TagID(), TemplateInt<Index - 1>());
}
#define GetCount(...) \
Highest<__COUNTER__, void>(__VA_ARGS__(), TemplateInt<CounterLimit>())
#define IncrementCount(TagID) \
template <unsigned int GetID, typename = typename std::enable_if<(GetID > __COUNTER__ + 1)>::type> \
constexpr unsigned int Highest( \
TagID, \
TemplateInt<GetCount(TagID) + 1> Value) \
{ \
return decltype(Value)::Value; \
}
Тестирование
struct Counter1 {};
struct Counter2 {};
constexpr unsigned int Read0 = GetCount(Counter1);
constexpr unsigned int Read1 = GetCount(Counter1);
IncrementCount(Counter1);
constexpr unsigned int Read2 = GetCount(Counter1);
IncrementCount(Counter1);
constexpr unsigned int Read3 = GetCount(Counter1);
IncrementCount(Counter1);
constexpr unsigned int Read4 = GetCount(Counter1);
IncrementCount(Counter1);
IncrementCount(Counter2);
constexpr unsigned int Read5 = GetCount(Counter1);
constexpr unsigned int Read6 = GetCount(Counter2);
int main(int, char**)
{
std::cout << "Ending state 0: " << Highest<__COUNTER__, void>(Counter1(), TemplateInt<0>()) << std::endl;
std::cout << "Ending state 1: " << Highest<__COUNTER__, void>(Counter1(), TemplateInt<1>()) << std::endl;
std::cout << "Ending state 2: " << Highest<__COUNTER__, void>(Counter1(), TemplateInt<2>()) << std::endl;
std::cout << "Ending state 3: " << Highest<__COUNTER__, void>(Counter1(), TemplateInt<3>()) << std::endl;
std::cout << "Ending state 4: " << Highest<__COUNTER__, void>(Counter1(), TemplateInt<4>()) << std::endl;
std::cout << "Ending state 5: " << Highest<__COUNTER__, void>(Counter1(), TemplateInt<5>()) << std::endl;
std::cout << Read0 << std::endl;
std::cout << Read1 << std::endl;
std::cout << Read2 << std::endl;
std::cout << Read3 << std::endl;
std::cout << Read4 << std::endl;
std::cout << Read5 << std::endl;
std::cout << Read6 << std::endl;
return 0;
}
выход
Ending state 0: 0
Ending state 1: 1
Ending state 2: 2
Ending state 3: 3
Ending state 4: 4
Ending state 5: 4
0
0
1
2
3
4
1
250 * 250 счетчик уровня
Если вы хотите более высокие значения, чем 256, я думаю, вы можете комбинировать счетчики. Я сделал 250 * 250 (хотя на самом деле я не проверял счет 2). CounterLimit должен быть снижен примерно до 250 для ограничения рекурсии времени компиляции. Просто чтобы заметить, это заняло у меня значительно больше времени для компиляции.
Осуществление
template <typename, unsigned int> struct ExtraCounter { };
template <unsigned int GetID, typename, typename TagID>
constexpr unsigned int LHighest(TagID)
{
return Highest<GetID, void>(ExtraCounter<TagID, CounterLimit>(), TemplateInt<CounterLimit>()) * CounterLimit +
Highest<GetID, void>(
ExtraCounter<TagID, Highest<GetID, void>(ExtraCounter<TagID , CounterLimit>(), TemplateInt<CounterLimit>())>(),
TemplateInt<CounterLimit>());
}
#define GetLCount(TagID) \
LHighest<__COUNTER__, void>(TagID())
#define LIncrementTag_(TagID) \
typename std::conditional< \
GetCount(ExtraCounter<TagID, GetCount(ExtraCounter<TagID, CounterLimit>)>) == CounterLimit - 1, \
ExtraCounter<TagID, CounterLimit>, \
ExtraCounter<TagID, GetCount(ExtraCounter<TagID, CounterLimit>)>>::type
#define IncrementLCount(TagID) \
template <unsigned int GetID, typename = typename std::enable_if<(GetID > __COUNTER__ + 7)>::type> \
constexpr unsigned int Highest( \
LIncrementTag_(TagID), \
TemplateInt<GetCount(LIncrementTag_(TagID)) + 1> Value) \
{ \
return decltype(Value)::Value; \
}
Тестирование
struct Counter3 {};
constexpr unsigned int Read7 = GetLCount(Counter3);
IncrementLCount(Counter3);
constexpr unsigned int Read8 = GetLCount(Counter3);