Search code examples
c++templatestemplate-specializationboost-mpltemplate-templates

Template specialization on typename parameter being any instantiation of a particular template


I have a class template Z that I would like specialize when passed a type that is an any instantiation of a particular template N:

struct L {
    template <typename S> void foo(S &) {/*...*/}
};

template <class T>
struct M {
    template <typename S> void foo(S &) {/*...*/}
};

template <class T>
struct N {
    template <typename S> void foo(S &) {/*...*/}
};

// I'd like to specialize this for TY==N<anything>
template <typename TX, typename TY>
struct Z {
    void bar(TX &tx) { /*...*/ ty->foo(tx); /*...*/ }
    TY *ty;
};

Since Z<int, L> and Z<int, N<int>> and Z<int, M<int>> are all valid use cases, I can't do anything along the lines of turning Z into a template template, and there is a compelling complexity reduction possible in Z<TX, TY>::bar(TX &) when TY is a class built from N. Is there a way to achieve this?


Solution

  • This should effect the specialization you desire:

    template <typename TX, typename ANY>
    struct Z< TX, N<ANY> > {
        // ...
    };
    

    Z gets specialized when the first parameter is TX, and the second parameter is N<ANY>. A quick illustration:

    template <typename A> struct N { A a; };
    
    template <typename TX, typename TY>
    struct Z { Z () { std::cout << "not special" << std::endl; } };
    
    template <typename TX, typename ANY>
    struct Z< TX, N<ANY> > { Z () { std::cout << "special" << std::endl; } };
    
    int main ()
    {
        Z<int, int> z1;
        Z<int, N<int> > z2;
    }
    

    Results in the output:

    not special
    special