How to partially specialize a class template for all derived types?

前端 未结 2 1887
执笔经年
执笔经年 2021-01-04 13:27

I want to partially specialize an existing template that I cannot change (std::tr1::hash) for a base class and all derived classes. The reason is that I\'m usin

相关标签:
2条回答
  • 2021-01-04 13:44

    Instead of modifying std::tr1::hash you should make your own namespace and define there new structure hash which inherited from std::tr1::hash or is specialized for CRTPBase<Derived>.

    
    template <typename Derived>
    struct CRTPBase
    {
        size_t hash() {return 0; }
    };
    
    struct AA : CRTPBase <AA> {};
    struct BB {};
    //
    namespace mynamespace {
    
    template <typename Some, typename Dummy=char> 
    struct hash : std::tr1::hash<Some> {};
    //
    template <typename Derived>
    struct hash<Derived, 
      typename boost::enable_if< std::tr1::is_base_of<CRTPBase<Derived>, Derived>, char>::type >
    {    
        size_t operator()(const CRTPBase<Derived> & base) const     
        {         
            return base.hash();     
        }
    };
    
    } // namespace mynamespace {}
    //
    //
    void ff()
    {
        using namespace mynamespace;
    
        hash<AA> aa;  // my hash
        hash<BB> bb;  // std::tr1::hash
    
    }
    
    0 讨论(0)
  • 2021-01-04 13:49

    There are two variants in the following code. You could choose more appropriated for you.

    
    template <typename Derived>
    struct CRTPBase
    {
        size_t hash() const {return 0; }
    };
    
    // First case 
    //
    // Help classes
    struct DummyF1 {};
    struct DummyF2 {};
    struct DummyF3 {};
    template<typename T> struct X; 
    
    // Main classes
    template<> struct X<DummyF1> : CRTPBase< X<DummyF1> > {
        int a1;
    };
    
    template<> struct X<DummyF2> : CRTPBase< X<DummyF2> > {
        int b1;
    };
    
    // typedefs
    typedef X<DummyF1> F1;
    typedef X<DummyF2> F2;
    typedef DummyF3    F3; // Does not work
    
    namespace std { namespace tr1 {
        template<class T>
        struct hash< X<T> > {
            size_t operator()(const CRTPBase< X<T> > & base) const     
            {         
                return base.hash();     
            }
        };
    }} // namespace tr1 // namespace std 
    
    //
    
    // Second case
    struct DummyS1 : CRTPBase <DummyS1> {
        int m1;
    };
    //
    template<typename T> 
    struct Y : T {};
    //
    typedef Y<DummyS1> S1;
    
    
    namespace std { namespace tr1 {
        template<class T>
        struct hash< Y<T> > {
            size_t operator()(const CRTPBase<T> & base) const     
            {         
                return base.hash();     
            }
        };
    }} // namespace tr1 // namespace std 
    
    void main1()
    {
        using std::tr1::hash;
        F1 f1;
        F2 f2;
        F3 f3;
        hash<F1> hf1; size_t v1 = hf1(f1); // custom hash functor
        hash<F2> hf2; size_t v2 = hf2(f2); // custom hash functor
        hash<F3> hf3; size_t v3 = hf3(f3); // error: standard hash functor
    
        S1 s1;
        hash<S1> hs1; size_t w1 = hs1(s1); // custom hash functor
    
    }
    
    0 讨论(0)
提交回复
热议问题