Transforming a parameterization by two classes to a parameterization by one class

后端 未结 3 2157
感情败类
感情败类 2021-01-22 14:33

The following code has a little bit of unpleasantness.

#include 

template struct PA1 {}; template struct QA1          


        
3条回答
  •  我在风中等你
    2021-01-22 15:06

    As I understand the question and its predecessors, the task is a specialization of function template on a class template regardless of its template parameter.

    Generic solution:

    #include 
    //remember the value of the argument S to retrieve it later
    template struct PA1 { typedef S S; };
    template struct PA2 { typedef S S; };
    template struct PB  { typedef S S; };
    template struct PC  { typedef S S; };
    
    //helper: generic version of fn for any parameters except PB и PC
    template
    struct FN
    {
        static char fn() { return 'a'; }
    };
    //helper: fn specialized for class template PB
    template
    struct FN, S>
    {
        static char fn() { return 'b'; }
    };
    //helper: fn specialized for class template PC
    template
    struct FN, S>
    {
        static char fn() { return 'c'; }
    };
    
    //fn relies on compiler's type deduction to avoid specifying of template parameter explicitly
    template
    char fn(T t)
    {
        return FN< T, T::S>::fn();
    }
    //usage
    int main()
    {
        PA1 pa1;
        PA2 pa2;
        PB  pb;
        PC  pc;
        assert( (fn(pa1)) == 'a' );
        assert( (fn(pa2)) == 'a' );
        assert( (fn(pb)) == 'b' );
        assert( (fn(pc)) == 'c' );
    }
    

    Applying this method to your case:

    #include 
    
    template struct PA1 { typedef S S; }; template struct QA1 {};
    template struct PA2 { typedef S S; }; template struct QA2 {};
    template struct PB  { typedef S S; }; template struct QB  {};
    template struct PC  { typedef S S; }; template struct QC  {};
    
    template struct A1 { typedef PA1 P; typedef QA1 Q; };
    template struct A2 { typedef PA2 P; typedef QA2 Q; };
    template struct B  { typedef PB  P; typedef QB  Q; };
    template struct C  { typedef PC  P; typedef QC  Q; };
    
    template
    struct FN
    {
        static char fn() { return 'a'; }
    };
    template
    struct FN, S>
    {
        static char fn() { return 'b'; }
    };
    template
    struct FN, S>
    {
        static char fn() { return 'c'; }
    };
    
    template
    char fn() //or char fn(A* a)
    {
        return FN::fn();
    }
    
    template
    struct Action
    {
        char z;
        //so the constructor accepts only correct combinations of p and q 
        Action(typename T::P p, typename T::Q q)
        {
            z = fn(); //or fn((T*)NULL);
        }
    };    
    int main()
    {
        PA1 pa1; QA1 qa1;
        PA2 pa2; QA2 qa2;
        PB  pb;  QB  qb;
        PC  pc;  QC  qc;
    
        Action > aa1 = Action >(pa1, qa1);    assert( aa1.z == 'a' );
        Action > aa2 = Action >(pa2, qa2);    assert( aa2.z == 'a' );
    
        Action > ab = Action >(pb, qb );    assert( ab.z == 'b' );
        Action > ac = Action >(pc, qc );    assert( ac.z == 'c' );
    }
    

提交回复
热议问题