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.
Related
class TestClass
{
public:
static int testMember;
template<class T> static T* Foo()
{
//Defination....
}
}
//int TestClass::testMember; //Duplicate definition
Why can't I define a member field in .hpp while I can define member functions in .hpp?
Does it must be defined in a .cpp file?
Why can't I define a member field in .hpp
You can.
C++ doesn't care what you name your files, and doesn't care what extension the files have.
What you can't do is define the variable more than once. That would obviously violate the one definition rule.
In order to satisfy the one definition rule, you have two options:
In C++17 or later, make the variable inline.
class TestClass
{
public:
static inline int testMember;
template<class T> static T* Foo()
{
//Defination....
}
}
In any version of C++, place the definition in your code where it will be compiled exactly once.
Why ... [can I] define member functions in .hpp?
Because member functions, defined in the class, are implicitly inline. Just like your variable could be.
As Drew Dormann has mentioned, template member functions (static or not) are implicitly inline.
The same goes for class templates:
template <typename>
class TestClass
{
public:
static int testMember;
template<class T> static T* Foo()
{
//Definition....
}
};
// prior to C++17 you definition MUST be outside the class in the header
template <typename T>
int TestClass<T>::testMember{};
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.
I am new to c++ (and to programming itself) and this is what I heard:
If we compile an ordinary function, The compiler creates a pointer to that function and place the instructions that make up the body of the function elsewhere. This is how an ordinary function gets compiled. But in case of inline functions, the compiler generates code during compilation and replaces it with the inline function call.
My question is when member functions (of a C++ class) are compiled, are they treated as inline functions or are they treated as ordinary functions?
They are just like normal functions, with one exception: if you write the function definition inside the class definition (example below), then the function is automatically given the inline keyword:
[C++11: 9.3/2]: A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition.
struct T
{
void foo() // the same as `inline void foo()`
{
// ...
}
};
That doesn't automatically mean the class will be inlined, though; the inline keyword is just a hint and is largely ignored nowadays when it comes to deciding whether to actually inline a function, though it does assuredly affect linkage.
You asked:
are they treated as inline functions or are they treated as ordinary functions?
Member functions of classes can be inline or non-inline depending on how they are declared and defined.
Here's the relevant info from the standard:
9.3 Member functions
2 A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition. A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition...
Example:
class A
{
A() : data(0) {} // Inline function
inline A(A const& copy) : data(copy.data) {}
// Inline function. The keyword inline
// can be used but not necessary.
int data;
};
3 An inline member function (whether static or non-static) may also be defined outside of its class definition provided either its declaration in the class definition or its definition outside of the class definition declares the function as inline. [ Note: Member functions of a class in namespace scope have external linkage. Member functions of a local class (9.8) have no linkage. See 3.5. —end note ]
Example:
class A
{
A(); // Declaration doesn't say whether the function is inline or not.
inline A(A const& copy); // Declaration says the function is inline.
int data;
};
inline A::A() : data(0) {} // Implementation says the function is inline.
inline A(A const& copy) : data(copy.data) {}
4 There shall be at most one definition of a non-inline member function in a program; no diagnostic is required. There may be more than one inline member function definition in a program. See 3.2 and 7.1.2.
Example:
class A
{
A(); // Declaration doesn't say whether the function is inline or not.
inline A(A const& copy); // Declaration says the function is inline.
int data;
};
inline A(A const& copy) : data(copy.data) {}
// Must be defined in a .h file since the declaration says the function is inline.
A::A() : data(0) {} // Non-inline implementation.
// It must be defined in only one translation unit (a .cpp file, not a .h file).
Whether to inline a function or not is entirely up to the compiler's discretion, which means that different compilers might have different criteria for function inlining. That being said, you can prompt the compiler to inline a function with keywords such as inline, __inline, and __forceinline. Still, it does not guarantee that your function will be inlined.
However, there are cases where it's generally impossible to inline. This link from Microsoft would probably give you a good idea about function inlining.
An example of a function that cannot be inlined will be a virtual function. As virtual function calls(i.e. which virtual function definition to call) are determined on run-time, it is impossible for the compiler to figure out which exact function definition will be called at each call of the virtual function.
#include <iostream>
class Base
{
public:
virtual int VirtualFunc();
};
class Derived1 : public Base
{
public:
virtual int VirtualFunc() { return 1; }
};
class Derived2 : public Base
{
public:
virtual int VirtualFunc() { return 2; }
};
int main(void)
{
Base* pBase;
size_t choice;
std::cin >> choice; //Get user input
if(choice == 1) //If user inputs 1, create a Derived1
pBase = new Derived1;
else if(choice == 2) //If user inputs 2, create a Derived2
pBase = new Derived2;
pBase->VirtualFunc(); //At compile-time, no idea if pBase will be Derived1 or Derived2
return 0;
}
Thank you for reading.
Compilation of class methods works same as standalone functions. If you put inline keyword before it, compiler will try to insert it's code to place, where it is called, if it's possible.
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() {}
};
I am using code::blocks, with, I believe gcc. Given the example code (this is pseudo code and may not replicate the problem):
//Assume this is in a separate header file to B
class TestA
{
protected:
int A;
public:
void Function1(){A = 0;}
};
class TestB : public TestA
{
public:
void CallFunction(){ A = 10; Function1();}//
};
I would get similar compile errors, like:
Error: 'A' not declared in this scope.
Error: Function1() not declared in this scope.
I was under the impression that all base variables and functions were inherited to the subclass. Given the base class has a lot of functions and variables, I don't want to use the 'using' keyword as I'd have to declare it for every function and variable (to my knowledge).
Is there any way to make it so TestB explicitly or actually includes the stuff it's inheriting?
Relevant snippets below
Okay. It's not possible to include example code as it's in project, but I will quote the key snippets:
C:\Users\user\Desktop\Projects\RND2\TemplateListAdv.h|30|error: 'Size' was not declared in this scope|
The line this is on is:
if(!Array.SetToSize(Size))
The class it's in is:
template<typename TemplateItem>
class TemplateListAdv : public TemplateList<TemplateItem>
And the incriminating line from TemplateList is:
SIZE_TYPE Size; //SIZE_TYPE is unsigned long.
//SIZE_TYPE is available in all files as unsigned long.
Files go:
TemplateList.h->TemplateBasics.h->TemplateListAdv.h
No missing files from what I can see.
I will tack in, the 'using' keyword resolves it individually, but this has been bugging me as I thought inheritance was automatic.
Compiler data as requested:
"Release 10.05 rev 6283 (2010-05-27 09:09:13) gcc 4.4.1 Windows/unicode - 32 bit"
So it looks like you are getting error wite template classes inheritance, isn't it? They are a big difference comparing to non-template ones. Assuming you have code like this:
template <class T>
class TestA
{
protected:
int A;
public:
void Function1(){A = 0;}
};
template <class T>
class TestB : public TestA<T>
{
public:
void CallFunction(){ A = 10; Function1();}//
};
The issue is caused by two-phase name lookup. All members of the base TestA class are dependent names, i.e. they depend on the template argument T. This is so because you can have template specialization for TestA with totally different members, e.g.:
template <class T>
class TestA
{
protected:
int A;
public:
void Function1(){A = 0;}
};
template <class T>
class TestB : public TestA<T>
{
public:
void CallFunction(){ A = 10; Function1();}//
};
template <>
class TestA<int>
{
};
Now, there is no A and Function1 members in the TestA, so they would be unaccessible in TestB as well. In order to let compiler know that these members are indeed depende on the template argument you should write TestB like this:
template <class T>
class TestB : public TestA<T>
{
public:
void CallFunction(){ this->A = 10; this->Function1();}//
};
This way you make compiler resolve names only during template instantiation time instead of template declaration time and it will known about base class members.
One thing to add is that there is no such issue with VC compiler, it doesn't try to parse templates until instantiation and thus don't support two-phase name lookup.
The problem that you're having about accessing base class stuff in a class template, is a FAQ item.
Rather then quoting the whole FAQ item here, I just link to it: that's your answer.
The code that you presented to illustrate the problem was unrelated, sorry. It is always a good idea to give an actual example rather than an example of what one thinks might be the problem.
Cheers & hth.,
The problem is that you are using templates, and the base class is a 'dependent name'. That is, the template base class could be specialized and not have the Size member, the compiler just doesn't know when it compiles your class, because the Size reference is not in a dependent context.
In your particular case the easiest solution is to refer to the inherited members using this:
if(!Array.SetToSize(this->Size))
And since this is a dependent name, it should work
Are you sure that :
Size is a protected or public attribute of TemplateList ?
you're not calling if(!Array.SetToSize(Size)) from a static method ?
The question is really bad, and you might want to improve on that. Anyway, my crystal ball tells me that Size is defined in a base template, and that because the identifier Size is not dependent lookup is not going into the base template and the compiler not seeing it. Add a this-> before Size and you should be set.
When interpreting a template member function, the compiler must (following the standard) decide for each symbol if it is dependent on the template parameter. If it is dependent on it, then it'll only be resolved when the template is instantiated. However, he must resolve it at this moment.
In your case, the compiler think that A and Function1 don't depend on the template parameter and should thus be resolvable just after the parse. You just have to make it depend on the template parameter by using this->A and this->Function1
So, you should have something like that.
template < typename T >
class Base
{
protected:
int A;
public:
void Function1() { A = 0; }
};
template < typename T >
class Derived : public Base< T >
{
public:
void CallFunction1() {
this->A = 10;
this->Function1();
}
};