Search code examples
c++11templatesc++14template-specializationpartial-specialization

Partial specialization of nested template template class


I am currently struggeling with partial template specialization of a template template (template ) class. I know we can realize the following problem with inheritance but the goal is to use only templates and template specialization.

Let's consider this piece of code:

template< typename T >
struct V4;
template< >
struct V4< float > {
    using point_type = std::array< float, 4 >;
};
template< typename T >
struct V12;
template< >
struct V12< int > {
    using point_type = std::array< int, 12 >;
};

template< typename T, template< typename = T > class IM >
struct Rectangle;
template< template< typename > class IM >
struct Rectangle< float, IM > {
    float get( size_t i ) { /*...*/ }
};

template< typename T, template< typename = T > class IM >
struct Polygon;
template< template< typename > class IM >
struct Polygon< int, IM > {
    float get( size_t i ) { /*...*/ }
};

The classes V2 and V12 can be considered as some kind of a wrapper classes for builtin-types or aggregates. The classes Rectangle and Polygon uses V2 or V12 and are partial specialized. So far so good. We can use this like the following:

Rectangle< float, V4 > a;
std::cout << a.get(1) << "\n";

Now what we want to achieve is a class which encapsulates some calculations on the introduces structs for instance. It should be called like this:

std::cout << CalculateSomething< Rectangle< float, V4 > >::doIt( ) << "\n";

CalculateSomething should be partial specializable regarding to wether it works with an Rectangle or an Polygon. So a possible specialization should look like this:

template< typename T >
struct CalculateCenter< Rectangle< T, V2 >, T > {
    static T doIt( ) {
        /*...*/
    }
};
template< typename T >
struct CalculateCenter< Polygon< T, V12 >, T > {
    static T doIt( ) {
        /*...*/
    }
};

The question now is: How to declare the template class CalculateCenter?

Thanks in advance


Solution

  • The answer seems rather straightforward:

    template < class T >
    struct CalculateCenter;
    
    template< typename T >
    struct CalculateCenter< Rectangle< T, V2 > > {
        static T doIt( ) {
            /*...*/
        }
    };
    
    template< typename T >
    struct CalculateCenter< Polygon< T, V12 > > {
        static T doIt( ) {
            /*...*/
        }
    };
    

    [Live example]