Inherit from non-specialized template (shared library) - c++

I'm getting "Unresolved External Symbols" when I'm inheriting directly from shared library class template, but if I specialize library template in my code first, it works fine.
Template class in shared library:
template <typename T>
class EventHandler
{
public:
virtual ~EventHandler();
virtual EventResult ReceiveEvent(T * evn, EventDispatcher<T> * dispatcher) = 0;
};
Derived class in my code (doesn't work without specialization):
class MyEventHandler : public EventHandler<SomeEventType>
{
public:
virtual EventResult ReceiveEvent(SomeEventType * evn, EventDispatcher<SomeEventType> * dispatcher);
};
Specialized library template class in my code:
template <>
class EventHandler<SomeEventType>
{
public:
virtual ~EventHandler() {}
virtual EventResult ReceiveEvent(SomeEventType * evn, EventDispatcher<SomeEventType> * dispatcher) = 0;
};
I tried reproducing it directly in shared lib's code (I have the source) and it worked fine without template specialization. Does it have anything to do with lib not giving access to full class implementation? In this case EventHandler template doesn't have any additional definitions in .cpp because it's just one pure virtual method.
Also my derived classes are inside the namespace if it matters.
[EDIT] class template of EventHandler doesn't have any additional implementation in .cpp file, this definition posted above from .h file is everything it does (one pure virtual function). It has nothing to do with thread suggested as possible duplicate.

The reason is that you don't have destructor definition in your EventHandler class. Your specialization does overload it, so compiler is not left without definition. Note, that this is the code that have to be defined in header file, not in cpp file (thus, being a part of library binary), because compiler has to instantiate new definition for every type with which EventHandler template type is specialized/instantiated.

Related

no out-of-line virtual method definitions for full-specialized template class

I have this kind of structure:
static lib A
interface.h
class Interface
{
public:
virtual ~Interface() // no pure virtual dtor
virtual void pureMethod1() = 0;
virtual void pureMethod2() = 0;
virtual void virtualMethod1();
virtual void virtualMethod2();
};
interface.cpp
include "interface.h"
Interface::~Interface() = default;
Interface::virtualMethod1() {}
Interface::virtualMethod2() {}
static lib B using A
BaseT.h
#include "interface.h"
template<class T>
class BaseT final : public Interface
{
static_assert(false, "can't use this specialization");
};
specialized1.h
#include "baset.h"
using MyType = BaseT<CustomClass1>;
template<>
class BaseT<CustomClass1> : public Interface
{
public:
BaseT() = default;
void pureMethod1() final {}
void pureMethod2() final {}
};
specialized2.h
#include "baset.h"
using MyType = BaseT<CustomClass2>;
template<>
class BaseT<CustomClass2> : public Interface
{
public:
BaseT() = default;
void pureMethod1() final {}
void pureMethod2() final {}
};
I'm receiving a warning from clang in both fully specialized classes:
warning: 'BaseT has no out-of-line virtual method definition: its vtable will be emitted in every translation unit'
Why this warning? I don't have any pure virtual destructor, and a defaulted one is provided in base class. And how I can avoid the out-of-line virtual method since I'm using a template?
The resloution of virtual functions is usually implemented by the use of a table of function pointers, the vtable. Each class implementing (i.e. inheriting from) the interface have such a table where the entries points to its implementation of the vitual functions. This table must be located in at least one of the object files generated during compilation and by default many compilers put it in the object file containing the implementation of the first virtual function in the class.
In your case all virtual functions in the specializations of BaseT are defined inline in the class declaration. In this case there is no unique object file to put their implementation in, they will be included in all object files where it is used. This in turn implies that the method of putting the vtable together with the implementation of the first virtual function will no longer work. This makes the compiler fall back to add a version of the vtable to all object files just to be safe and to make the programmer aware of this it issues a warning.
This is not really a problem since the linker will choose the vtable from one of the object files and include in the final binary.
This warning occurs, because your virtual function implementation is located in a header file.
Header files are just pasted inside ccp-files with #include directive. So your file will be pasted into multiple cpp-files. And as implementation is provided inside class, it's separate for each cpp-file. Therefore, for each object files all instantiations will be generated
There is no simple way to avoid that, but there are a few possible solutions. The simple solution is finding single cpp that uses the implementation.
Another workaround is just getting rid of templates in place where the methods are implemented, i.e
class ImplForCustomClass2 : public Interface
{
public:
virtual void pureMethod1() final override;
virtual void pureMethod2() final override;
};
template<>
class Base<CustomClass2> : public ImplForCustomClass2
{};
There are more ways to avoid it, though. You can try finding a way that suits you more.

How to inherit template abstract class with a class with template secification

I have a project on linux that builds into static library, which then I want to include in unit test project and in app project.
In this library I have something like that:
template<class T> class A
{
public:
virtual T doStuff() = 0;
virtual void doOther(T a) = 0;
protected:
A() { ... }
};
class B : public A<int>
{
public:
B() { ... }
virtual int doStuff() { ... }
virtual void doOther(int a) { ... }
};
I am getting compilation error: undefined reference to A<int>::A() in my lib.
I'm guessing it has something to do with template generation, and also can I override virtual functions like that?
templates are generated during compile time and needs to be implemented in the same translation unit they are prototyped. So, if you are including a declaration of a templated class, you also need to include the definition.
So, it would be prudent to have both the declaration and definition in the same header file, so that, any module that intends to use it, when compiled can generate the definition as required.
Refer:
14.7.2 Explicit instantiation [temp.explicit]
For a given set of template arguments, if an explicit instantiation of
a template appears after a declaration of an explicit specialization
for that template, the explicit instantiation has no effect.
Otherwise, for an explicit instantiation definition the definition of
a function template, a member function template, or a member function
or static data member of a class template shall be present in every
translation unit in which it is explicitly instantiated.

Specialize template with a subclass of an abstract class

I'm stuck with the following issue:
I've got a class Test with template T. When I create an object of this class, specializing with other common class, everything works fine. In the constructor of class Test there is one line of code which creates an object of the template class;
But when I try to instantiate this class (Test), specializing it with a subclass (SubDummy) of an abstract class (Dummy), I get an error: cannot instantiate an abstract class.
Example code (simplified to the purpose of this post):
class Dummy
{
private:
virtual void _nothing() = 0; // this makes the class abstract
};
class SubDummy : public Dummy
{
public:
SubDummy() :
Dummy()
{
}
};
template <class T>
class Test
{
public:
Test()
{
T t; // here the compiler reports the error
}
};
int main()
{
Test<SubDummy> x;
}
Classes containing pure virtual member functions simply cannot be instantiated. Since you didn't specify an override for _nothing in SubDummy, it is a pure virtual in this class as well. You must implement _nothing in SubDummy in order to make it work.
Sometimes, when debugging templates it's useful to think of what the class becomes when you instantiate it with the variables.
class TestWithSubDummy {
public:
TestWithSubDummy() {
SubDummy t;//the error
}
};
You are pretty obviously trying to instantiate a SubDummy (using the default constructor) at the error. But SubDummy is abstract, so we aren't allowed to instantiate it. Thus, the error.

How to instantiate an instance of the current class in a static method?

I have a Qt class that looks something like this:
class MyClass : public QObject
{
Q_OBJECT
public:
virtual void doSomething();
static void createInstance();
};
The createInstance method is supposed to create an instance of the current class and invoke the doSomething method on it. For example, if I create a derived class named MyOtherClass, createInstance should create an instance of MyOtherClass and invoke doSomething on that instance.
At first I thought templates might be a solution here, but the following code:
template <typename T>
static void createInstance();
// ...in myclass.cpp...
template <typename T>
void MyClass::createInstance()
{
T().doSomething();
}
...produces the following linker errors:
error: undefined reference to `void MyClass::createInstance<MyOtherClass>()'
This answer might have worked except moc doesn't work with template classes. What options do I have?
Put the implementation of createInstance in your header file. Each compilation unit that uses createInstance<Foo> needs to be able to create the implementation.
As an improvement, create a two-tier system:
class MyClassBase: public QObject {
Q_OBJECT
public:
virtual void doSomething() = 0;
};
template<typename Derived>
class MyClass: public MyClassBase {
public:
static void createInstanceAndDoSomething() {
Derived d;
d.doSomething();
}
};
then, when inheriting from MyClass, pass in the derived class:
class DerivedClass: MyClass<DerivedClass> {
// ...
};
you can also throw in some static (or, if your compiler doesn't have that) runtime asserts that Derived is a derived class of MyClass<Derived> in the body of MyClass<Derived>. Just to keep things sane.
By only using Q_OBJECT in concrete classes (and not in template classes), I'm hoping your moc will be able to deal with it. The template class merely exists in order to create static method with compile time dispatch without having to write it again and again and again, and without having to repeat yourself every time you call it. If not, you can always fall back to the first version.

how to implement Singleton in C++

This post is what I just read.
The way he implements Singleton in C++ confuses me. I got several Questions about it and here is his code:
template<typename T>
class Singleton {
public:
static T& getInstance() { //Question 1
return instance;
}
private:
static T instance;
};
class DebugLog : public Singleton<DebugLog> { //Question 2
public:
void doNothing() {}
};
Question
I think we should put the static T& getInstance()'s definition outside of the class body, right?
He tries to make class DebugLog a singleton class, but when he inherits Singleton<DebugLog>, the DebugLog doesn't already exist, right? If right, then how can the template class Singleton instantiate an un-existent class?
1) Nope, it doesn't matter how you structure your code. Singleton isn't a class, by the way: It's a template. Since the full template definition must be visitible at any instantiation site anyway, you might as well define everything inline.
2) class DebugLog : public Singleton<DebugLog> is fine. We are not inheriting from a non-existing class; rather, we are inheriting from the class Singleton<DebugLog>. Templates can be instantiated on incomplete types. (There are several rules what you can and cannot do with such a type parameter.)
For example, template <typename T> class Foo { }; can certainly be instantiated on any type without problem. More interestingly, template <typename T> struct PointerFactory { typedef T * type; }; can be instantiated on any type, complete or not. In the present situation, the purpose of the template parameter in the CRTP is solely to inform the base class of its eventual derived type, so this is entirely fine.
It would certainly be cleaner if the function were defined outside of
the class, and make the code easier to read and to maintain. In this
case, however, the complete class is small enough that the difference
isn't very great, and of course, because we're dealing with a template,
the actual definition still has to be included in every translation unit
which uses it.
The C++ standard doesn't speak of “existence” with regards to classes (or anything
else). At the point of template instantiation, name lookup finds
DebugLog, and finds that it is a class (thus, a type). At that point,
it is an incomplete type, and there are only limited things you can do
with an incomplete type. If the class template which is instantiated
doesn't do anything that requires a complete type (and Singleton
doesn't), then there is no problem. (Note that only the class
definition is instantiated at this point; class member functions will
not be instantiated until they are used.)
I might add that there is still one important thing missing from the
code you posted: there is no definition for the declaration
Singleton::instance. You still need to add a:
template<typename T> T Singleton<T>::instance;
somewhere.
You must use a pointer to T in this case:
template<typename T>
class Singleton {
public:
static T& getInstance() {
static T * instance = NULL;
if (!instance)
instance = new T;
return *instance;
}
};
class DebugLog : public Singleton<DebugLog> { //Question 2
public:
void doNothing() {}
};