【问题标题】:Can I create a template (non-type) param class that can take any enum? C++11我可以创建一个可以采用任何枚举的模板(非类型)参数类吗? C++11
【发布时间】:2019-02-28 06:46:58
【问题描述】:

这里是一些在模板上进行递归的示例代码的 sn-p。我正在尝试创建一个算法,该算法采用任何枚举(来自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;
}

我想将此创建为一个“通用”算法,该算法可以采用 any 枚举(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;

}

【问题讨论】:

  • 我对此不是 100% 确定,但我认为应该使用 SFINAE...typename std::enable_if&lt;std::is_enum&lt;E&gt;::value, E&gt;::type 之类的东西。抱歉,我现在没有时间写完整的答案。

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


【解决方案1】:

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

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

我能想象的最好的是以下

#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();
 }

如果(何时)可以使用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 <auto>
struct traits
 { static void do_something() {} };

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

      TT::do_something();

      attr_engine<static_cast<decltype(F)>(F - 1u)>::set();
    }
 };

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 2022-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多