Question

I'm writing a template <class T> array-like class A, and I want to specialize a few member functions to deal with arrays of arrays A<A<T>>.

Here is an working example that is close to what I want:

#include "stdio.h"

//primary template class 
template <class T> class A {
public: void f() {printf("A<T>::f\n");}
};

//1st solution : specialization (?) of A for A<A<T>>
template <class T> class A< A<T> > {
public: void f() {printf("A<A<T>>::f\n");}
};

//2nd solution : specialization of A::f for A<A<int>>
template<> void A< A<int> >::f() {
    printf("A<A<int>>::f\n");
}

int main(void) {

    A<int> A_int;
    A< A<int> > A_A_int;
    A< A<double> > A_A_double;

    A_int.f();        // ok : prints A<T>::f
    A_A_int.f();      // ok : prints A<A<int>>::f
    A_A_double.f();   // ok : prints A<A<T>>::f

    return 0;
}

The problem with 1st solution is that I have to duplicate a lot of member functions from the primary template class

I tried to derive from the primary class but

template <class T> class A< A<T> > : public A< A<T> >

makes no sense

The problem with 2nd solution is that I have to duplicate the specialization for every possible types, and that defeats the purpose of template classes.

Since it is possible to define template<> void A< A<int> >::f(), it seems one should be able to "templatize" this specialization for any type. I tried :

template <class T> template<> void A< A<T> >::f()
template <template <class T> > void A< A<T> >::f()
template <template <> class T> void A< A<T> >::f()

and other absurd syntaxes...

So... Can I templatize the specialization template<> void A< A<int> >::f() not just for int but for any type T ?

Thanks in advance,

Best regards,

Was it helpful?

Solution

One possible way:

#include <cstdio>

// forward declaration
template<typename>
class A;

template<typename>
class A_Base {
    // general case
    public: void f() { printf("A<T>::f\n"); }
};

// partial specialization for any A
template<typename T>
class A_Base< A<T> > {
    // special stuff
    public: void f() { printf("A<A<T>>::f\n"); }
};

template<typename T>
class A : private A_Base<T> { // private inheritance, we're not modeling IS-A
public:
    using A_Base<T>::f;  // make f accesible

    // all the other stuff that doesn't need to change
};

int main()
{
    A<int> a1;
    A<A<int>> a2;
    a1.f();       // A<T>::f
    a2.f();       // A<A<T>>::f
}

This way you put only the functions that need to behave differently in the base class. You can of course make it vice-versa - you put common code in the base class and specialize a derived class where you also define f.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top