Stateful compile-time counter mechanism based on function overloading and ADL.
#include <scl/utility/preprocessor/counter.h>Contents:
SCL_COUNTER_VALUE(Tag)Reads the current value of a compile-time counter identified by Tag.
#include <scl/utility/preprocessor/counter.h>#define SCL_COUNTER_VALUE(Tag) /* ... */Counter<int> and Counter<float> are independent).constexpr value of type std::uint_fast32_t.SCL_COUNTER_NEXT invocations for its tag.#include <scl/utility/preprocessor/counter.h>
struct MyTag {};
constexpr auto v0 = SCL_COUNTER_VALUE(MyTag);
static_assert(v0 == 0);
SCL_COUNTER_NEXT(MyTag)
constexpr auto v1 = SCL_COUNTER_VALUE(MyTag);
static_assert(v1 == 1);
SCL_COUNTER_NEXT(Tag)Increments a compile-time counter identified by Tag.
#include <scl/utility/preprocessor/counter.h>#define SCL_COUNTER_NEXT(Tag) /* ... */scl::preprocessor::detail that causes subsequent SCL_COUNTER_VALUE(Tag) calls to return a higher value.#include <scl/utility/preprocessor/counter.h>
struct TagA {};
struct TagB {};
// Two independent counters
constexpr auto a0 = SCL_COUNTER_VALUE(TagA); // 0
constexpr auto b0 = SCL_COUNTER_VALUE(TagB); // 0
SCL_COUNTER_NEXT(TagA)
constexpr auto a1 = SCL_COUNTER_VALUE(TagA); // 1
constexpr auto b1 = SCL_COUNTER_VALUE(TagB); // still 0
SCL_COUNTER_NEXT(TagA)
SCL_COUNTER_NEXT(TagB)
constexpr auto a2 = SCL_COUNTER_VALUE(TagA); // 2
constexpr auto b2 = SCL_COUNTER_VALUE(TagB); // 1
#include <scl/utility/preprocessor/counter.h>
template <typename T>
struct TypeCounter {};
constexpr auto int_v0 = SCL_COUNTER_VALUE(TypeCounter<int>);
static_assert(int_v0 == 0);
SCL_COUNTER_NEXT(TypeCounter<int>)
constexpr auto int_v1 = SCL_COUNTER_VALUE(TypeCounter<int>);
static_assert(int_v1 == 1);
// A different specialization is a separate counter
constexpr auto float_v0 = SCL_COUNTER_VALUE(TypeCounter<float>);
static_assert(float_v0 == 0);
SCL_FORWARD macro is used internally to handle template tags that contain commas.