mercredi 27 février 2019

Can I create a template (non-type) param class that can take any enum? C++11

Here is a snippet of some example code that does recursion on templates. I am trying to create an algorithm that takes any enum (from 0...n, sequential) and performs an 'algorithm' based on those values using traits (does this recursively by subtracting the largest enum by 1).

#include <iostream>
using namespace std;

enum enum_type : size_t
{
    DEFAULT = 0,
    ONE = 1,
    TWO = 2,
    THREE = 3,
    FOUR = 4,
    MAX = FOUR,
};

template < enum_type F >
struct traits;

template < >
struct traits<ONE>
{
    static void do_something() {}
};

template < >
struct traits<TWO>
{
    static void do_something() {}
};

template < >
struct traits<THREE>
{
    static void do_something() {}
};

template < >
struct traits<FOUR>
{
    static void do_something() {}
};

template < enum_type F, typename TT = traits<F> >
struct attr_engine
{
    static void set()    {
        printf("Number: %lu ", F);

        TT::do_something();

        // get a compile error of trying to subtract an enum to an integer
        constexpr enum_type NEXT_FIELD = static_cast<enum_type>(F - 1);
        attr_engine<NEXT_FIELD>::set();
        return;
    }
};

template < >
struct attr_engine<DEFAULT, traits<DEFAULT>>
{
    static void set()    {
    printf("Reached the end");
    return;
    }
};

int main()
{
   attr_engine<MAX>::set();

   return 0;
}

I would like to create this into a "generic" algorithm that can take any enum (enum_type2 instead of only enum_type, etc.) but I'm not quite sure how to to do this with non-type template params, or it is even possible.

I can't use typename because I'm using a non-type template param.

template < typename F, typename TT = traits<F> >
struct attr_engine

As an alternative, I've considered using a size_t potentially:

template < size_t F, typename TT = traits<F> >
struct attr_engine

But trying to create a generic F that can be deduced into its appropriate trait is something I'm stuck on. I need some new approaches. I'm worried that doing that would cause me to cast the input non-template param which looks messy.

enum enum_type2
{
    DEFAULT_ENUM2,
    ONE_VAL,
    TWO_VAL,
    THREE_VAL,
    FOUR_VAL,
    ENUM2_MAX = FOUR_VAL,
};

int main()
{
   attr_engine<static_cast<sizet>(ENUM2_MAX)>::set();

   return 0;

}

Aucun commentaire:

Enregistrer un commentaire