0
votes

Given:

template<typename T> 
struct Foo
{
    template<typename U>
    struct Bar {};

    /* many more members */
}

and

template<typename F> 
struct Zoo {};

I need that only Bar will be specialized for when enclose class Foo is of type of Foo<Zoo<F>> whatever F is. I don't want to partial specialize Foo for Zoo<F> because I need then to declare all its members again.

I don't understand why the follow won't compile:

template<typename F>
template<typename U>
struct Foo<Zoo<F>>::Bar {}

because I would expect Foo<Zoo<F>> to be treated as the primary Foo template , where its template parameter is set to Zoo<F>, and only Bar should be specialized.

1

1 Answers

0
votes

A friend gave me the solution and I share.

According to the c++ standard :

“Each class template partial specialization is a distinct template and definitions shell be provided for the members of a template partial specialization”

That's is the reason why the code won't compile. Foo<Zoo<F>> is a partial specialization of Foo and in this case, according to the C++ standard, the compiler doesn't use the primary template but expect for a distinct definition.

Solution 1: Define partial specialization of enclosing class

We must define first the specialization for Foo<Zoo<F>> but if we already define it, then we actually can specialize Bar within this definition.

// partial specialization of Foo 
template<typename T> 
struct Foo<Zoo<T>>
{
    template<typename U>
    struct Bar { /* specialize declaration for Bar here */ };

    /* many more members - should be define here as in the primary template of Foo */
};

This will give the desired results, but the problem is that we have to define all Foo other members again in the specialization.

Solution 2: Move declaration of nested class into a base class

// base class contains only declaration of Bar
template<typename T> 
struct FooBase
{
    template<typename U>
    struct Bar {};
};

// Foo contains other members, but also derived from FooBase
template<typename T> 
struct Foo : public FooBase<T>
{
    /* many members */
};

In order to specialize Bar for when Foo is of type of Foo<Zoo<T>> , we define the partial specialization of FooBase.

// partial specialization of FooBase 
template<typename T> 
struct FooBase<Zoo<T>>
{
    template<typename U>
    struct Bar { /* specialize declaration for Bar here */ };
};