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

Сообщение Самый честный компайл-тайм счётчик на свете!!! от 27.11.2024 15:42

Изменено 27.11.2024 16:06 rg45

Самый честный компайл-тайм счётчик на свете!!!
Привет всем!

Сразу огромное спасибо 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);
}
Самый честный компайл-тайм счётчик на свете!!!
Привет всем!

Сразу огромное спасибо 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);
}