将一个通用枚举类型作为模板参数 [英] Give a generic enum type as template argument

查看:562
本文介绍了将一个通用枚举类型作为模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之:



有一种方法,我可以喂一个一般模板类, 枚举类型?例如:

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

< int>



b b ul>
  • 模板 Holder 类以通用方式处理任何类型的数据。

  • code>一般类实现依赖于 Holder s行为的特定算法。

  • 模板规格一般(如 IntSpecific DoubleSpecific StringSpecific MoreSophisticatedTypeSpecific ..)定义如何处理一些具体 Holder 类型。

  • 如何正确定义 EnumSpecific 规范?



  • 这里是boilt down代码,使我的问题发生:

      
    template< typename T>
    class Holder {
    public:
    Holder(T const& t):_value(t){};
    //通用方法
    void generics(){};
    //有关值的方法:
    void set(T const& t / *,setInfo * /){
    // ..检查实际变化,通知变化的好友。 。
    _value = t;
    };
    T值(/ * readInfo * /){
    // ..取决于如何/为什么值被读取的东西
    return _value;
    };
    private:
    T _value;
    };
    //(在现实中,所有`generics`方法来自一个父类,未经考虑的类)

    //一个涉及这样的`Holder`s的泛型过程:
    template<类型名T>
    class General {
    public:
    typedef bool / *或anything * / KnownReturnTypes;
    General(Holder< T> * const a
    ,Holder< T> * const b)
    :_a(a)
    ,_b(b)
    { ;
    void methods(){
    //使用所有`Holder`的
    的常见行为_a> generics();
    // ..或依赖于实际值的方法:
    KnownReturnTypes knr(valuedMethods());
    if(knr){} else {}
    // ...
    };
    //使用多态来适应每种情况..
    virtual KnownReturnTypes valuedMethods()= 0;
    protected:
    Holder< T> * _a;
    Holder< T> * _b;
    };

    //整数类型的特殊化示例(可能有其他)
    class IntSpecific:General< int> {
    public:
    IntSpecific(Holder< int> * const a
    ,Holder< int> * const b)
    :General< int>(a,b)
    {};
    //实现valuedMethods:
    virtual KnownReturnTypes valuedMethods(){
    return _a-> value()> _b-> value(); // dummy
    }
    };

    //枚举类型的专用化:
    // * * * class EnumSpecific:General< any_enum_type> {//不存在* *
    类EnumSpecific:General< int> {
    public:
    EnumSpecific(Holder< int> * const a
    ,Holder< int> * const b)
    :General< int>(a,b)
    {};
    //只使用枚举类型提供的属性和方法:
    virtual KnownReturnTypes valuedMethods(){
    return _a-> value()== _b-> value() // dummy
    }
    };

    //一个特殊情况
    typedef枚举{一,二,三}枚举;
    typedef Holder< Enum>枚举器


    int main(){

    //检查`IntSpecific`是否正常。
    Holder< int> * i(new Holder< int>(3));
    Holder< int> * j(new Holder< int>(5));
    IntSpecific是(i,j); // 好。

    //尝试'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
    //这是因为编译器不知道什么
    // EnumSpecific实际上是*是*。如何告诉他更多关于它?


    return EXIT_SUCCESS;
    }

    我应该在 EnumSpecific :



    我需要使用某种类型的

    解决方案

    我们可以使用 href =http://en.cppreference.com/w/cpp/types/enable_if =nofollow> std :: enable_if 和< a href =http://en.cppreference.com/w/cpp/types/is_enum =nofollow> std :: is_enum 。作为示例,这是一个类,它将枚举类型作为模板参数。

      #include< type_traits& 
    枚举枚举{FOO,BAR};

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

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


    In short:

    Is there a way I can feed a General templated class with something that only represent an enum type? Something like:

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

    <int> is too much / does not work in my case.


    My specific case:

    • A templated Holder class handles any kind of data in a generic way.
    • An abstract General class implements specific algorithms relying on the Holders' behaviour.
    • Template specifications of General (like IntSpecific, DoubleSpecific, StringSpecific, MoreSophisticatedTypeSpecific ..) define how to deal with some concrete Holder types.
    • How can I properly define an EnumSpecific specification?

    Here is boilt down code making my problem occur:

    // 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;
    }
    

    What should I feed the template argument with in EnumSpecific : General<??> to make things clear for the compiler?

    Do I need to use some kind of enum_type concept and more sophisticated tools from generic programming?

    解决方案

    We can accomplish this with std::enable_if and std::is_enum. As a sample this is a class that will take an enum type as a template parameter.

    #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
    }
    

    这篇关于将一个通用枚举类型作为模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆