【问题标题】:Give a generic enum type as template argument给出一个通用枚举类型作为模板参数
【发布时间】:2015-11-25 19:41:10
【问题描述】:

简而言之:

有没有一种方法可以为 General 模板化类提供仅代表 enum 类型的内容?比如:

template <typename T> struct General {};
struct EnumSpecific : General<any_enum_type> {};

&lt;int&gt; 太多/在我的情况下不起作用。


我的具体情况:

  • 模板化的Holder 类以通用方式处理任何类型的数据。
  • 一个抽象的General 类实现依赖于Holders 行为的特定算法。
  • General 的模板规范(如IntSpecificDoubleSpecificStringSpecificMoreSophisticatedTypeSpecific ..)定义了如何处理一些具体的Holder 类型。
  • 如何正确定义EnumSpecific 规范?

这是导致我的问题发生的归结代码:

// A templated value holder:
template <typename T>
class Holder {
public:
    Holder(T const& t) : _value(t) {};
    // generic methods
    void generics() {};
    // methods concerning the value:
    void set(T const& t /*, setInfo */) {
        // .. check for an actual change, notify buddies of the change..
        _value = t;
    };
    T value(/*readInfo*/) {
        // .. do stuff depending on how / why the value is read..
        return _value;
    };
private:
    T _value;
};
// (in reality, all `generics` methods come from a parent, untemplated class)

// A generic process involving such `Holder`s:
template <typename T>
class General {
public:
    typedef bool /* or anything */ KnownReturnTypes;
    General(Holder<T>* const a
          , Holder<T>* const b)
        : _a(a)
        , _b(b)
    {};
    void methods() {
        // Use common behavior of all `Holder`'s
        _a->generics();
        // .. or methods that rely on the actual values:
        KnownReturnTypes knr( valuedMethods() );
        if (knr) {} else {}
        // ...
    };
    // Use polymorphism to adapt to each situation..
    virtual KnownReturnTypes valuedMethods() = 0;
protected:
    Holder<T>* _a;
    Holder<T>* _b;
};

// Example of specialization for integral types (there might be others)
class IntSpecific : General<int> {
public:
    IntSpecific(Holder<int>* const a
              , Holder<int>* const b)
        : General<int>(a, b)
    {};
    // implement the valuedMethods:
    virtual KnownReturnTypes valuedMethods() {
        return _a->value() > _b->value(); // dummy
    }
};

// Specialization for enum types:
// * * * class EnumSpecific : General<any_enum_type> { // does not exist * *
class EnumSpecific : General<int> {
public:
    EnumSpecific( Holder<int>* const a
                , Holder<int>* const b)
        : General<int>(a, b)
    {};
    // only use properties and methods offered by an enum type:
    virtual KnownReturnTypes valuedMethods() {
        return _a->value() == _b->value(); // dummy
    }
};

// One particular case
typedef enum {One, Two, Three} Enum;
typedef Holder<Enum> EnumHolder;


int main() {

    // Check that `IntSpecific` works fine.
    Holder<int>* i( new Holder<int>(3) );
    Holder<int>* j( new Holder<int>(5) );
    IntSpecific is(i, j); // ok.

    // Try the `EnumSpecific`
    EnumHolder* a( new EnumHolder { One } );
    EnumHolder* b( new EnumHolder { Two } );
    EnumSpecific es(static_cast<Holder<int>*>(a)    // invalid cast
                  , static_cast<Holder<Enum>*>(b)); // unexpected type
    // This is because the compiler doesn't know enough about what
    // EnumSpecific actually *is*. How to tell him more about it?


    return EXIT_SUCCESS;
}

我应该在EnumSpecific : General&lt;??&gt; 中提供什么模板参数以使编译器清楚?

我是否需要使用某种enum_type 概念和泛型编程中更复杂的工具?

【问题讨论】:

  • C++11 给你std::is_enum:en.cppreference.com/w/cpp/types/is_enum
  • @AlanStokes 他真可爱!但这不能自己提供模板参数,可以吗?这对我表演演员有何帮助?
  • 它可以与enable_if 一起使用,从而获得收益。 underlying_type 可能会对你的演员阵容有所帮助,尽管我承认在那个阶段我有点迷失在你的代码中。

标签: c++ templates generics enums concept


【解决方案1】:

我们可以通过std::enable_ifstd::is_enum 完成此操作。作为示例,这是一个将枚举类型作为模板参数的类。

#include <type_traits>
enum Enum { FOO, BAR};

template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
class Test {};

int main()
{
    Test<Enum> a; // ok
    Test<double> b; // error
}

【讨论】:

  • 阿夫!我无法让这个工作。 #include &lt;type_traits&gt; 应该足以使用您的代码吗? gcc 说error: no type named ‘type’ in ‘struct std::enable_if&lt;false, void&gt;
  • 这是你应该得到的错误。如果 enable_if 被传递 false 则 type typedef 不存在并且它会产生编译器错误。错误后应该有一个注释,例如:note: while substituting prior template arguments into non-type template parameter ...
  • 糟糕!当然。我只是感到困惑,因为clangtemplate 行上找到了错误。这对我来说仍然很神奇:您知道漫游的优秀 C++ 泛型编程教程吗?比template &lt;typename T&gt; 更进一步,涵盖了那些新的 C++11 惊人的东西?
  • 这里有一些好书:stackoverflow.com/questions/388242/…
  • 太棒了!我玩了一下这个,这确实有效!特质真棒。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多