How to call a member function of the primary class template from a specialization, without modifying the primary template

117 views Asked by At

I am looking for a way to call the primary class template member function from a member function in a class template specialization. This is similar to the way we can call the base class virtual member function from overriden derived class member function.

// Template defintion
template <typename T>
class MyClass final
{
    ...
    void foo() { ... };
}
// Template specialization for method foo
template<>
void MyClass<MyType>::foo()
{
   ...
   // call primary template's foo() here??
   // MyClass::free(); // Warning: All paths through this function will call itself
}

Note: I do not own the code containing the primary template definition, only the template specialization part. I am looking for solutions within these restrictions. There is a similar question How to call a member function of the primary class template from the member function of a specialization without these restrictions, and I cannot use the answers there.

2

There are 2 answers

0
Klaus On

You can simply call your primary none specialized template by using a new type, which you don't have specialized before.

Something like:

 template < typename T>
struct MyClass 
{
    void Foo() { std::cout << "PrimaryFoo" << std::endl; }
};

template <>
void MyClass<double>::Foo() 
{
    std::cout << "Spezialized for double" << std::endl; 
    // and now call the primary template
    // simply define a type where MyClass is not specialized for
    struct Dummy;
    MyClass<Dummy>{}.Foo();
}

int main()
{
    MyClass<double>{}.Foo();
}

Quite clear that this will not help if you need your primary class to have the same data type as your specialization because it access some data in it.

1
Jan Schultke On

There is no clean way to accomplish your task. When you're asking

How do I call MyClass<X>::foo from MyClass<Y>::foo?

... that's like asking

How do I call std::string::size() from std::vector<char>::size()?

It is simply not possible; you are working with separate types. The only thing MyClass<X> and MyClass<Y> have in common is the name.

If you were allowed to modify the primary template, then you could make all MyClass inherit from a MyClassBase class (template), and that could contain the member unspecialized member function. You could create a new instance of MyClass<X> and call its MyClass<X>::foo, but this would only access the data members of this new object.

One possible solution is to inherit from something which uses the primary template:

template <typename T>
struct MyClass {
    /* ... */
    void foo() { /* ... */ }
};

template <>
struct MyClass<MyType> : private MyClass<void> {
    void foo() { // this is not overriding; it is shadowing
        // ...
        MyClass<void>::foo(); // call primary template member function
    }
};

This does solve the problem, but it also means that you inherit all the data members of the MyClass<void> (or other) base class.