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

Сообщение Re[2]: Простенький компайл-тайм счетчик от 30.03.2017 10:06

Изменено 30.03.2017 10:09 Кодт

Re[2]: Простенький компайл-тайм счетчик
Здравствуйте, jazzer, Вы писали:

J>Я сделал в свое время похожую штуку — и напоролся на ограничение рекурсии инстанцирования для сколько-нибудь больших файлов. Но это было давно, может, сейчас это и не проблема уже...


Вместо линейной рекурсии можно сделать деревянную!
template<int I> struct int_ { static constexpr int value = I; };
using int_0 = int_<0>;
using int_1 = int_<1>;

template<int I> struct point : int_0 {};
#define TAG_IT() template<> struct point<__COUNTER__> : int_1 {};

template<int L, int N> struct sumpoints;
template<int L, int H, int N> using splitsum = int_< sumpoints<L,H>::value + sumpoints<L+H,N-H>::value >;

template<int L> struct sumpoints<L, 0> : int_0 {};
template<int L> struct sumpoints<L, 1> : point<L> {};
template<int L, int N> struct sumpoints : splitsum<L, N/2, N> {};
    // лучше разбивать не пополам, а по старшему биту, - это даст меньше сочетаний <L,N> при массовом использовании
    // и, соответственно, меньше воплощений шаблона
    // но я сходу не вспомнил формулу для его нахождения

#define GET_IT() (sumpoints<0, __COUNTER__>::value)

constexpr int x = GET_IT();  // __COUNTER__ = 1, x = 0
constexpr int y = GET_IT();  // __COUNTER__ = 2, y = 0
TAG_IT();                    // __COUNTER__ = 3
TAG_IT();                    // __COUNTER__ = 4
TAG_IT();                    // __COUNTER__ = 5
constexpr int z = GET_IT();  // __COUNTER__ = 6, z = 3
Re[2]: Простенький компайл-тайм счетчик
Здравствуйте, jazzer, Вы писали:

J>Я сделал в свое время похожую штуку — и напоролся на ограничение рекурсии инстанцирования для сколько-нибудь больших файлов. Но это было давно, может, сейчас это и не проблема уже...


Вместо линейной рекурсии можно сделать деревянную!

http://ideone.com/E7VreH
template<int I> struct int_ { static constexpr int value = I; };
using int_0 = int_<0>;
using int_1 = int_<1>;

template<int I> struct point : int_0 {};
#define TAG_IT() template<> struct point<__COUNTER__> : int_1 {};

template<int L, int N> struct sumpoints;
template<int L, int H, int N> using splitsum = int_< sumpoints<L,H>::value + sumpoints<L+H,N-H>::value >;

template<int L> struct sumpoints<L, 0> : int_0 {};
template<int L> struct sumpoints<L, 1> : point<L> {};
template<int L, int N> struct sumpoints : splitsum<L, N/2, N> {};
    // лучше разбивать не пополам, а по старшему биту, - это даст меньше сочетаний <L,N> при массовом использовании
    // и, соответственно, меньше воплощений шаблона
    // но я сходу не вспомнил формулу для его нахождения

#define GET_IT() (sumpoints<0, __COUNTER__>::value)

constexpr int x = GET_IT();  // __COUNTER__ = 1, x = 0
constexpr int y = GET_IT();  // __COUNTER__ = 2, y = 0
TAG_IT();                    // __COUNTER__ = 3
TAG_IT();                    // __COUNTER__ = 4
TAG_IT();                    // __COUNTER__ = 5
constexpr int z = GET_IT();  // __COUNTER__ = 6, z = 3