Search code examples
c++templatestemplate-specializationpartial-specialization

How to specialize a class template with a template template parameter?


I'd like to specialize a class template on the type template parameter of the template template parameter. Is it possible? If yes, what is the syntax?

#include <type_traits>

template <typename T>
struct X {};

// primary template
template<template<class> class C>
struct Z : std::false_type {};

// specialization on the template template parameter
template<>
struct Z<X> : std::true_type {}; // OK

// specialization on the type template parameter of the
// template template parameter
template <template<class> class C>
struct Z<C<int>> {}; // ERROR

Motivation: Let's assume that the template template parameter denotes Collections (e.g. std::vector, std::deque). And I want to specialize Z on std::vector but I am not interested about the type template parameter of std::vector, that's OK. Also I want to specialize on all Collection types, which holds an int.

This question is similar to the following questions, but they are either trying to specialize a function template

or they are trying to specialize not on the template template parameter

or there's no template template parameter in the primary template


Solution

  • The following code compiles fine:

    #include <type_traits>
    
    template <typename T>
    struct X {};
    
    // primary template, no template template parameter
    template<typename T>
    struct Z : std::false_type {};
    
    // specialization on the template template parameter with arbitrary T
    template<typename T>
    struct Z<X<T>> : std::true_type {};
    
    // here's where you need the template template parameter
    template <template<class> class C>
    struct Z<C<int>> : std::true_type {};
    
    int main()
    {
        static_assert(!Z<Z<double>>::value, "" );
        static_assert( Z<Z<int   >>::value, "" );
        static_assert( Z<X<double>>::value, "" );
    //  static_assert( Z<X<int   >>::value, "" ); // error: ambiguous 
                                                  // partial specialization
    }
    

    In your code you give Z a template template parameter, even though that should be done for the specialization only. That's why your code does not compile.