LoginSignup
1

More than 5 years have passed since last update.

enum type traits

Last updated at Posted at 2018-01-29

以前別のブログで書いた内容だが、一応Qiitaにも書いておこうかなと思った次第

概要

enumに応じてtype traitsを決定する
似たようなものとしてはこちらがあげられる

source

template<class Enum>
struct selector {
    template<
        bool Check,
        size_t N,
        Enum Select,
        Enum First,
        Enum ... Modes
    >
    struct resolve_select
    {
        static size_t const value = N - 1;
    };

    template<
        size_t N,
        Enum Select,
        Enum First,
        Enum ... Modes
    >
    struct resolve_select<false, N, Select, First, Modes ...> :
        public resolve_select<First == Select, N + 1, Select, Modes ...>{};

    template<
            size_t N,
            class Check,
            class ... Remain>
    struct resolve_type : public resolve_type<N - 1, Remain ... > {};

    template<
        class Check,
        class ... Remain>
    struct resolve_type<0, Check, Remain ...>
    {
        typedef Check type;
    };

    template<Enum ... Modes>
    struct which {
        template<Enum Select>
        struct select {
            template<class ... Types>
            struct types {
                typedef typename resolve_type<resolve_select<false, 0, Select, Modes ..., Select>::value, Types ...>::type type;
            };
        };
    };
};

usage

こんな感じで使う

enum class Test {
    hoge,
    fuga,
};
template<Test Selector>
struct select {
    using type = typename switch_types<Test>::which<hoge,fuga>::select<Selector>::template types<int,long>::type;
};
//select<hoge>::type -> int
//select<fuga>::type -> long

Boost.PPと組み合わせると

#define TEST
(( hoge, int )) \
(( fuga, long )) \

#define REFERENCE_PARAM_ENUM(params) \
BOOST_PP_TUPLE_ELEM(2,0,params)

#define REFERENCE_PARAM_CLASS(params) \
BOOST_PP_TUPLE_ELEM(2,1,params)

#define REFERENCE_FORMAT_ENUM(z,index,params) \
BOOST_PP_COMMA_IF(index) REFERENCE_PARAM_ENUM(BOOST_PP_SEQ_ELEM(index,params))

#define REFERENCE_FORMAT_CLASS(z,index,params) \
BOOST_PP_COMMA_IF(index) REFERENCE_PARAM_CLASS(BOOST_PP_SEQ_ELEM(index,params))


#define JOINER_GEN_STRUCT(name,enum_type,params) \
template<enum_type Selector> \
struct name { \
    using type = typename util::switch_types<enum_type>::which<BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(params),REFERENCE_FORMAT_ENUM,params)>::select<Selector>::template types<BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(params),REFERENCE_FORMAT_CLASS,params)>::type; \
} \

JOINER_GEN_STRUCT(select,Test,TEST)

//select<hoge>::type -> int
//select<fuga>::type -> long

みたいな感じで書ける

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1