Re[2]: Простенький компайл-тайм счетчик
От: rg45 СССР  
Дата: 29.03.17 14:33
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, rg45, Вы писали:


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


Сейчас это тоже проблема. Я вот буквально вчера мерял на 2015-й студии — максимально допустимая глубина такой рекурсии — 495. Наверное, этим можно как-то управлять, но предел будет в любом случае.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Простенький компайл-тайм счетчик
От: jazzer Россия Skype: enerjazzer
Дата: 29.03.17 14:38
Оценка: +1
Здравствуйте, rg45, Вы писали:

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


R>Сейчас это тоже проблема. Я вот буквально вчера мерял на 2015-й студии — максимально допустимая глубина такой рекурсии — 495. Наверное, этим можно как-то управлять, но предел будет в любом случае.


Да, тут, разве что, вставлять промежуточные UPDATE, когда такая ошибка вылазит. Или какой-нибудь
#define TOUCH_CTC(name) \
   template <> struct name<__LINE__> : name<__LINE__ - 1> \
   { \
      static constexpr int value = name<__LINE__ - 1>::value; \
   };

который не изменит значения счетчика
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Простенький компайл-тайм счетчик
От: rg45 СССР  
Дата: 29.03.17 21:05
Оценка: +1
Здравствуйте, jazzer, Вы писали:

J>Да, тут, разве что, вставлять промежуточные UPDATE, когда такая ошибка вылазит. Или какой-нибудь

J>
J>#define TOUCH_CTC(name) \
J>   template <> struct name<__LINE__> : name<__LINE__ - 1> \
J>   { \
J>      static constexpr int value = name<__LINE__ - 1>::value; \
J>   };
J>

J>который не изменит значения счетчика

Так ведь и того проще — нет даже необходимости явно определять value, проблема решается простым наследованием:

#define TOUCH_CTC(name) \
   template <> struct name<__LINE__> : name<__LINE__ - 1> { };


В то же время я думаю, что эта проблема не будет возникать слишком часто при разумном подходе к структурированию программного кода.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Простенький компайл-тайм счетчик
От: Кодт Россия  
Дата: 30.03.17 09:23
Оценка:
Здравствуйте, rg45, Вы писали:

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

R>Сейчас это тоже проблема. Я вот буквально вчера мерял на 2015-й студии — максимально допустимая глубина такой рекурсии — 495. Наверное, этим можно как-то управлять, но предел будет в любом случае.

Управляется каким-то ключом (я, помню, игрался с этим давно).
Вот именно поэтому __COUNTER__ предпочтительнее __LINE__. Особенно, если мало кто будет им пользоваться.
Перекуём баги на фичи!
Re[2]: Простенький компайл-тайм счетчик
От: Кодт Россия  
Дата: 30.03.17 10:06
Оценка: 21 (1) :)
Здравствуйте, 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
Перекуём баги на фичи!
Отредактировано 30.03.2017 10:09 Кодт . Предыдущая версия .
Re[3]: Простенький компайл-тайм счетчик
От: Кодт Россия  
Дата: 30.03.17 11:29
Оценка:
К> // лучше разбивать не пополам, а по старшему биту, — это даст меньше сочетаний <L,N> при массовом использовании
К> // и, соответственно, меньше воплощений шаблона
К> // но я сходу не вспомнил формулу для его нахождения

Наверно, можно вот такое
constexpr int pivot(unsigned N) {
  int r = N & (N-1); // обнуление младшего бита
  return r ? r : N/2;
}

То есть, мы просто с другого направления заедем при построении поразрядного дерева.
Например, нам надо взять суммы <0,7>, <0,11> и <0,12>.

Дихотомией
0,7 =  0,3             + 3,4
       0,1 + 1,2         3,2       + 5,2
             1,1 + 2,1   3,1 + 4,1   5,1 + 6,1

0,11 = 0,5                   + 5,6
       0,2       + 2,3         5,3             + 8,3
       0,1 + 1,1   2,1 + 3,2   5,1 + 6,2         8,1 + 9,2
       ===   ===   ===   ###         6,1 + 7,1         9,1 + 10,1
                                     ===

0,12 = 0,6                   + 6,6
       0,3 + 3,3               6,3             + 9,3
       ###   3,1 + 4,2         6,1 + 7,2         9,1 + 10,2
             ===   4,1 + 5,1   ===   7,1 + 8,1   ===   10,1 + 11,1
                   ===   ===         ===   ===         ====

=== — повторно использованные воплощения точек
### — повторно использованные воплощения сумм
Т.е. 0,7 породил 13 воплощений, 0,11 добавил 14, 0,12 добавил 10.

Разбивкой по старшему разряду
0,7 =  0,4                   + 4,3
       0,2       + 2,2         4,2       + 6,1
       0,1 + 1,1   2,1 + 3,1   4,1 + 5,1

0,11 = 0,8                   + 8,3
       0,4 + 4,4               8,2       + 10,1
       ###   4,2 + 6,2         8,1 + 9,1
             ###   6,1 + 7,1
                   ===

0,12 = 0,8 + 8,4
       ###   8,2 + 10,2
             ###   10,1 + 11,1
                   ====

Получилось 13 + 10 + 4.

Разбивкой по младшему разряду
0,7 =  0,6                               + 6,1
       0,4                   + 4,2
       0,2       + 2,2         4,1 + 5,1
       0,1 + 1,1   2,1 + 3,1

0,11 = 0,10                              + 10,1
       0,8                   + 8,2
       0,4 + 4,4               8,1 + 9,1
       ###   4,2 + 6,2
             ###   6,1 + 7,1
                   ===

0,12 = 0,10 + 10,2
       ####   10,1 + 11,1
              ====

Получилось 13 + 10 + 3.
Перекуём баги на фичи!
CTC без препроцссора - помогите довести до ума!
От: rg45 СССР  
Дата: 13.04.17 21:32
Оценка:
Это не готовая реализация CTC, а только прототип, упрощенный до предела так, чтобы видна была идея.

Достоинства:

Недостатки:


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),
};
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 14.04.2017 8:16 rg45 . Предыдущая версия . Еще …
Отредактировано 13.04.2017 22:16 rg45 . Предыдущая версия .
Отредактировано 13.04.2017 21:53 rg45 . Предыдущая версия .
Отредактировано 13.04.2017 21:33 rg45 . Предыдущая версия .
Re: CTC без препроцссора - помогите довести до ума!
От: kov_serg Россия  
Дата: 14.04.17 09:52
Оценка: +1
Здравствуйте, rg45, Вы писали:

Лучше раскажите где вы используете compile time counter ?
Re[2]: CTC без препроцссора - помогите довести до ума!
От: rg45 СССР  
Дата: 14.04.17 10:05
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Лучше раскажите где вы используете compile time counter ?


Если кратко, декларативное описание больших структур данных, генерация типов, элементы рефлексии, сериализация, ввод-вывод.

Абстрактно, чуть детальнее. Представь, есть шаблонное объявление каких-то свойств
template <size_t> struct MemeberTraits;


При помощи CTC мы можем определить семейство специализаций:

CREATE_CTC<MemberCounter>

template <>
struct MemeberTraits<GET_CTC<MemberCounter>> // MemeberTraits<0>
{
  //...
};
template <>
struct MemeberTraits<GET_CTC<MemberCounter>> // MemeberTraits<1>
{
  //...
};
template <>
struct MemeberTraits<GET_CTC<MemberCounter>> // MemeberTraits<2>
{
  //...
};


Внутри каждой из специализаций разместить набор статических свойств, специфичных, например, для членов какого-то класса. Или для элеметнов списка типов, или для перечисления, или для элементров интрузивного профайлера, или... После этого эти наборы специализаций можно использовать для авотматической генерации, например, классов сериализации-десериализации, конверторов, аксессоров к базам данных... В общем, дофига всего.

Этот подход позволяет сколько угодно добавлять новые структуры данных, изменять и расширять существующие, не меняя при этом процедур работы с этими данными (сериализация/десериализация, вычитка/запись из/в БД, ввод-вывод, конверторы и пр).
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 14.04.2017 10:53 rg45 . Предыдущая версия . Еще …
Отредактировано 14.04.2017 10:51 rg45 . Предыдущая версия .
Отредактировано 14.04.2017 10:39 rg45 . Предыдущая версия .
Отредактировано 14.04.2017 10:39 rg45 . Предыдущая версия .
Отредактировано 14.04.2017 10:35 rg45 . Предыдущая версия .
Отредактировано 14.04.2017 10:25 rg45 . Предыдущая версия .
Отредактировано 14.04.2017 10:09 rg45 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.