Skip to content

File counter.h

File List > module > utility > src > scl > utility > preprocessor > counter.h

Go to the documentation of this file

#pragma once

#include <scl/utility/preprocessor/forward.h>

#include <cstdint>
#include <type_traits>

namespace scl::preprocessor::detail
{
    template <::std::uint_fast32_t N>
    using counter = ::std::integral_constant<::std::uint_fast32_t, N>;

    template <typename Tag, ::std::uint_fast32_t Rank, ::std::uint_fast32_t Acc>
    constexpr counter<Acc>
    crumb(Tag /*tag*/, counter<Rank> /*rank*/, counter<Acc> /*acc*/) // NOLINT(readability-named-parameter)
    {
        return {};
    }
} // namespace scl::preprocessor::detail

#define SCL_COUNTER_CRUMB(Tag, rank, acc)                                                   \
    ::scl::preprocessor::detail::crumb(Tag{}, ::scl::preprocessor::detail::counter<rank>(), \
        ::scl::preprocessor::detail::counter<acc>())

#define SCL_COUNTER_VALUE(Tag)                                                                                                                                                 \
    (SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 0,                                                                                                                             \
        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 1,                                                                                                                          \
            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 2,                                                                                                                      \
                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 3,                                                                                                                  \
                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 4,                                                                                                              \
                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 5,                                                                                                          \
                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 6,                                                                                                      \
                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 7,                                                                                                  \
                                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 8,                                                                                              \
                                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 9,                                                                                          \
                                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 10,                                                                                     \
                                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 11,                                                                                 \
                                                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 12,                                                                             \
                                                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 13,                                                                         \
                                                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 14,                                                                     \
                                                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 15,                                                                 \
                                                                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 16,                                                             \
                                                                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 17,                                                         \
                                                                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 18,                                                     \
                                                                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 19,                                                 \
                                                                                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 20,                                             \
                                                                                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 21,                                         \
                                                                                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 22,                                     \
                                                                                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 23,                                 \
                                                                                                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 24,                             \
                                                                                                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 25,                         \
                                                                                                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 26,                     \
                                                                                                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 27,                 \
                                                                                                                    SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 28,             \
                                                                                                                        SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 29,         \
                                                                                                                            SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 30,     \
                                                                                                                                SCL_COUNTER_CRUMB(SCL_FORWARD(Tag), 1ul << 31, \
                                                                                                                                    0))))))))))))))))))))))))))))))))          \
            .value)

#define SCL_COUNTER_NEXT(Tag)                                                                          \
    namespace scl::preprocessor::detail                                                                \
    {                                                                                                  \
        constexpr counter<SCL_COUNTER_VALUE(SCL_FORWARD(Tag)) + 1> crumb(Tag,                          \
            counter<(SCL_COUNTER_VALUE(SCL_FORWARD(Tag)) + 1) & ~SCL_COUNTER_VALUE(SCL_FORWARD(Tag))>, \
            counter<(SCL_COUNTER_VALUE(SCL_FORWARD(Tag)) + 1) & SCL_COUNTER_VALUE(SCL_FORWARD(Tag))>)  \
        {                                                                                              \
            return {};                                                                                 \
        }                                                                                              \
    }

// http://b.atch.se/posts/non-constant-constant-expressions/
// http://b.atch.se/posts/constexpr-counter/#prereq-adl
// https://stackoverflow.com/questions/44267673/is-stateful-metaprogramming-ill-formed-yet
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2118

// namespace scl
//{
//     template < typename Tag_ >
//     class counter
//     {
//         using Value = int;

//        template < Value n >
//        struct Index
//        {
//            friend constexpr Value adlValue ( Index< n > );
//        };

//        template < Value n >
//        struct Writer
//        {
//            friend constexpr Value adlValue ( Index< n > ) { return n; }
//            static constexpr Value value = n;
//        };

//        template < Value n >
//        static constexpr Value increment ( float, Index< n > )
//        { return n; }

//        template < Value n, Value = adlValue( Index< n >{} ) >
//        static constexpr Value increment ( Value, Index< n >, Value v = increment( 0, Index< n + 1 >{} ) ) { return v; }

//    public:
//        template < Value n = 0 >
//        static constexpr Value next ( Value v = value_of< Writer< increment( 0, Index< 0 >{} ) + n > > ) { return v + 1; }

//        template < Value n = 0 >
//        static constexpr Value value ( Value v = value_of< Writer< increment( 0, Index< 0 >{} ) + n - 1 > > ) { return v + 1; }
//    };
//}