Самый честный компайл-тайм счётчик на свете!!!
От: rg45 СССР  
Дата: 27.11.24 15:42
Оценка: 16 (4)
Привет всем!

Сразу огромное спасибо vopl за наводку: http://rsdn.org/forum/cpp/8849463.1
Автор: vopl
Дата: 08.11 11:41


Благодаря этому финту с энтропией, удалось получить новую имплементацию компайл-тайм счётчика, лишённую ВСЕХ недостатков, присущих предыдущим версиям. Новый счетчик представляет собой простой шаблон переменной, параметризуемый произвольным типом (т.е. каждый счётчик привязывается к определенному типу). Счётчики можно применять в любых областях видимости (неймспейс, функция, класс). И главное — данная реализация вообще не использует препроцессор!

Вот здесь, собственно, вся реализация:

http://coliru.stacked-crooked.com/a/2f1f2e2384a2031d

#include <iostream>

namespace compile_time
{

   template <typename T, typename E = decltype([] {}) >
   concept Complete = requires {
      {sizeof(T)};
      typename E;
   };
   template <typename T, typename E = decltype([] {}) >
   concept Incomplete = !Complete<T, E>;

   template <typename T, size_t I>
   struct Declaration { friend constexpr auto test(Declaration); };

   template <typename T, size_t I>
   struct Definition {
      friend constexpr auto test(Declaration<T, I>) { return I; }
      friend constexpr auto test(Definition) { return test(Declaration<T, I>{}); }
   };

   template <typename T, size_t I, typename E = decltype([] {}) >
   concept Defined = Complete<decltype(test(Declaration<T, I>{})), E > ;

   template <typename T, size_t I, typename E = decltype([] {}) >
   concept Undefined = !Defined<T, I, E>;

   template <typename T, size_t I, typename E = decltype([] {}) >
   struct FindCurrentFrom : FindCurrentFrom<T, I + 1, E> {};

   template <typename T, size_t I, typename E>
      requires Undefined<T, I, E>
   struct FindCurrentFrom<T, I, E> : std::integral_constant<size_t, I> {};

   template <typename T, typename E = decltype([] {}) >
   inline constexpr size_t ct_peek = FindCurrentFrom<T, 0, E>::value;

   template <typename T, typename E = decltype([] {}) >
   inline constexpr size_t ct_tick = test(Definition<T, ct_peek<T, E>>{});

} // namespace compile_time

using compile_time::ct_peek;
using compile_time::ct_tick;

int main()
{
   static_assert(ct_tick<int> == 0);
   static_assert(ct_tick<class X> == 0);
   static_assert(ct_tick<void> == 0);

   struct Inner
   {
      static_assert(ct_tick<int> == 1);
      static_assert(ct_tick<class X> == 1);
      static_assert(ct_tick<void> == 1);

      static_assert(ct_peek<int> == 2);
      static_assert(ct_peek<class X> == 2);
      static_assert(ct_peek<void> == 2);
   };

   static_assert(ct_tick<int> == 2);
   static_assert(ct_tick<class X> == 2);
   static_assert(ct_tick<void> == 2);

   static_assert(ct_tick<int> == 3);
   static_assert(ct_tick<class X> == 3);
   static_assert(ct_tick<void> == 3);
}
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.11.2024 16:08 rg45 . Предыдущая версия . Еще …
Отредактировано 27.11.2024 16:06 rg45 . Предыдущая версия .
Отредактировано 27.11.2024 15:50 rg45 . Предыдущая версия .
Отредактировано 27.11.2024 15:42 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.