我可以创建一个可以接受任何枚举的模板(非类型)参数类吗? C ++ 11

时间:2019-02-28 06:46:58

标签: c++ c++11 templates enums template-meta-programming

这是一些对模板进行递归的示例代码的片段。我正在尝试创建一种算法,该算法接受任何枚举(从0...n开始,依次使用)并基于这些值使用特征执行“算法”(通过将最大枚举减去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;
}

我想将其创建为一个“通用”算法,该算法可以采用任何枚举(enum_type2而非仅enum_type等),但我不是非常确定如何使用非类型模板参数执行此操作,甚至有可能。

我不能使用typename,因为我使用的是非类型模板参数。

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

作为替代方案,我考虑过可能使用std::size_t

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

但是,我坚持尝试创建一个可以推论为适当特性的通用F。我需要一些新方法。我担心这样做会导致我转换看起来很乱的输入非模板参数。

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;

}

1 个答案:

答案 0 :(得分:1)

  

我想将其创建为可以接受任何枚举(“ enum_type2”而不是“ enum_type”等)的“通用”算法,但是我不太确定如何使用非类型模板参数来执行此操作,或者甚至有可能。

您标记了C ++ 11,因此不能使用auto作为模板类型参数(从C ++ 17开始可用),因此必须将{{1 }}您正在使用。

我能想象的最好的是以下

enum

(如果)可以使用C ++ 17,一切都会变得简单

#include <iostream>

enum enum_type : std::size_t
 { DEFAULT = 0, ONE, TWO, THREE, FOUR, MAX = FOUR, };

enum enum_type2 : std::size_t
 { DEFAULTbis = 0, ONEbis, TWObis, THREEbis, MAXbis = THREEbis, };

template <typename ET, ET F>
struct traits
 { static void do_something() {} };

template <typename ET, ET F, typename TT = traits<ET, F>, typename = void>
struct attr_engine
 {
   static void set ()
    {
      std::cout << "Number: " << F << std::endl;

      TT::do_something();

      constexpr ET NEXT_FIELD = static_cast<ET>(F - 1u);
      attr_engine<ET, NEXT_FIELD>::set();
    }
 };

template <typename ET, ET F>
struct attr_engine<ET, F, traits<ET, F>,
                   typename std::enable_if<0u == F>::type>
 { static void set() { std::cout << "Reached the end" << std::endl; } };

int main ()
 {
   attr_engine<decltype(MAX), MAX>::set();
   attr_engine<decltype(MAXbis), MAXbis>::set();
 }