dlw
dlw

Reputation: 323

Template instantiation of abstract class

I have a question on mixing templates and inheritance in C++, where I am unsure if what I am doing is disallowed by the standard, or just an implementation thing, or me making a mistake.

When browsing through the related questions on SO, I found that many snippets are quite non-minimal, or a matter of a forgotten template<> or some such thing (not pointing a finger, I too get confused about template syntax all the time). So I tried to boil this down to a minimal, conceptual question.

Example

I have a templated, abstract class Foo

// Foo.hpp
template <typename T>
class Foo
{
  virtual T doSomethingAbstract() = 0;
  T doSomething();
};

and

#include "Foo.hpp"
template class Foo<double>;

template <typename T>
T Foo<T>::doSomething()
{
  // implementation
}

This works fine with gcc (4.7 and 4.8) and clang (3.4) when I put the implementation into the header file, i.e. I can inherit from Foo and instantiate it with -say- double, so I believe "I know that -mainly due to complexity- virtual template methods aren't allowed." does not hold unqualified (not anymore maybe? C++11? I am not required to use any -std=c++11 or so, it works without).

It compiles both with and without explicit instantiation template class Foo<double>; and nm tells me that (only) with explicit instantiation some code is actually produced, like this

$ nm -C Foo.o 
                 U __cxa_pure_virtual
0000000000000000 V typeinfo for Foo<double>
0000000000000000 V typeinfo name for Foo<double>
0000000000000000 V vtable for Foo<double>
                 U vtable for __cxxabiv1::__class_type_info

However, if this were well-defined and legal, there should be an implementation of Foo<double>::doSomething() somewhere.

Question

Is it legal to force partial template instantiation for the non-abstract member and leave the remaining instantiations of the abstract ones to the children? In my youthful naivity, I thought this should be feasible and legal, but then again we are talking C++; the compilers surely beg to differ.

Upvotes: 1

Views: 683

Answers (1)

Anton Savin
Anton Savin

Reputation: 41301

The problem is not in virtual functions, but in the point of explicit template instantiation. You have to put explicit template instantiation at the bottom of implementation file, so it knows about all implementation details at that point:


// Foo.cpp
#include "Foo.h"

template <typename T>
T Foo<T>::doSomething()
{
    return doSomethingAbstract();
}

template class Foo<double>;

// main.cpp
#include "Foo.h"

class Foo2 : public Foo<double> {
public:
    double doSomethingAbstract() {
        return 0;
    }
};

int main() {
    Foo2 foo;
    foo.doSomething();
}

Upvotes: 1

Related Questions