Templated superclass linking problem - c++

I'm trying to create a C++ class, with a templated superclass. The idea being, I can easily create lots of similar subclasses from a number of superclasses which have similar characteristics.
I have distilled the problematic code as follows:
template_test.h:
template<class BaseClass>
class Templated : public BaseClass
{
public:
Templated(int a);
virtual int Foo();
};
class Base
{
protected:
Base(int a);
public:
virtual int Foo() = 0;
protected:
int b;
};
template_test.cpp:
#include "template_test.h"
Base::Base(int a)
: b(a+1)
{
}
template<class BaseClass>
Templated<BaseClass>::Templated(int a)
: BaseClass(a)
{
}
template<class BaseClass>
int Templated<BaseClass>::Foo()
{
return this->b;
}
main.cpp:
#include "template_test.h"
int main()
{
Templated<Base> test(1);
return test.Foo();
}
When I build the code, I get linker errors, saying that the symbols Templated<Base>::Templated(int) and Templated<Base>::Foo() cannot be found.
A quick Google suggests that adding the following to main.cpp will solve the problem:
template<> Templated<Base>::Templated(int a);
template<> int Templated<Base>::Foo();
But this does not solve the problem. Adding the lines to main.cpp does not work either. (Though, interestingly, adding them to both gives 'multiply defined symbol' errors from the linker, so they must be doing something...)
However, putting all the code in one source file does solve the problem. While this would be ok for the noddy example above, the real application I'm looking at would become unmanageable very fast if I was forced to put the whole lot in one cpp file.
Does anyone know if what I'm doing is even possible? (How) can I solve my linker errors?
I would assume that I could make all the methods in class Templated inline and this would work, but this doesn't seem ideal either.

With templated classes, the definitions must be available for each translation unit that uses it. The definitions can go in a separate file, usually with .inl or .tcc extension; the header file #includes that file at the bottom. Thus, even though it's in a separate file, it's still #included for each translation unit; it cannot be standalone.
So, for your example, rename template_test.cpp to template_test.inl (or template_test.tcc, or whatever), then have #include "template_test.inl" (or whatever) at the bottom of template_test.h, just before the #endif of the include guard.
Hope this helps!

The problem is that when your Templated file is compiled, the compiler doesn't know what types it will need to generate code for, so it doesn't.
Then when you link, main.cpp says it needs those functions, but they were never compiled into object files, so the linker can't find them.
The other answers show ways to solve this problem in a portable way, in essence putting the definitions of the templated member functions in a place that is visible from where you instantiate instances of that class -- either through explicit instantiation, or putting the implementations in a file that is #included from main.cpp.
You may also want to read your compiler's documentation to see how they recommends setting things up. I know the IBM XLC compiler has some different settings and options for how to set these up.

The C++ FAQ-lite covers this, and a couple of ways round it.
You don't have to make all the methods "inline", but you should define the method bodies in template_test.h, rather in template_test.cpp.
Some compilers can handle this split, but you have to remember that at one level, templates are like macros. for the compiler to generate the a template for your particular , it needs to have the template source handy.

When the compiler is compiling main.cpp, it sees the class definition has member function declarations, but no member function defintions. It just assumes that there must be a definition of "Templated" constructor and Foo implementation somewhere, so it defers to the linker to find it at link time.
The solution to your problem is to put the implementation of Templated into template.h.
eg
template<class BaseClass>
class Templated : public BaseClass
{
public:
Templated(int a) : BaseClass(a) {}
virtual int Foo() { return BaseClass::b; }
};
Interestingly, I could get your code to link by putting this at the end of template_test.cpp.
void Nobody_Ever_Calls_This()
{
Templated<Base> dummy(1);
}
Now the compiler can find an instance of Templated to link with. I wouldn't recommend this as a technique. Some other file might want to create a
Templated<Widget>
and then you'd have to add another explicit instantiation to template_test.cpp.

Related

Class method inline definitions

I find it a very appealing programming style define all the methods of a struct/class directly inline in the struct, eg only define structs this way:
"A.hpp"
class A;
"A.cpp"
class A
{
A() = default;
void method() { }
};
rather than
"A.hpp"
class A
{
A();
void method();
};
"A.cpp"
A::A() = default;
void A::method() { }
This means putting classes/struct definitions in a code file and only including declaration in header files.
However, this runs into the problems when the compiler would need to know the struct/class layout in other code files.
Is there a programming style that supports this? Perhaps only getting and setting fields through getters/setters? This way would however lead to large amounts of boilerplate.
Just including the struct/class definition in the header file leads to issues with mutually recursive header files, unless one explicitly puts the declarations in another.
I can achieve this programming style in a language like D with a module system, but how does one achieve it in C++?
What are you doing is called forward declaration.
You will be not able to do anything (f.e. call methods, create instances) with this class in all other translation units, except one .cpp file, where you define it. So, this idea is completely useless and bad. And you will get a boatload of linker errors.
So, you need to either stick to style #2. Or define inline methods in header file, like this
struct A {
A() {} // something
int func() { /* function body */
}

C++ only implementation of template class

I do not have access to c++11 for this project.
I have a C++ class; lets call it Bar, it looks something like this:
Header FooBar.h:
#include "Fancy.h" // <--- Dependency
namespace Foo
{
template<typename T>
class Bar : public Fancy::FancyClass<T, ALLOCATER<HARD_CODED_VALUE>>
{
};
}
Cpp:
None
Fancy is a lib that is being statically linked into a dll. The problem is that when other projects want to use the dll they include "FooBar.h" it says that it cannot find "Fancy.h"
Basically I want projects that include the dll to be able to use this class without needing any additional libraries or headers.
My solution was to just put it in a cpp and have no header file. Unfortintly nothing can find it then? I have tried creating a blank header file that did not work either.
I tried to forward declare it in the header but to do that I need the .h to understand what FancyClass is. I have also tried
namespace Fancy
{
class FancyClass;
class ALLOCATER;
}
namespace Foo
{
template<typename T>
class Bar : public Fancy::FancyClass<T, ALLOCATER<HARD_CODED_VALUE>>;
}
in the header. But that causes many errors.
Short answer, you must include the header in your executable file in order to use the provided library.
Long(er) answer, the compiler needs to know the structure of the class defined in the library.
Imagine that there is a class called MyAwesomeClass that is part of a library you want to use in your executable. The compiler doesn't know anything about that class when you say MyAwesomeClass awesome;. How big is it? What methods can you call on it? Does it inherit from anything?
This information is contained in the header file where the class is declared.
class MyAwesomeClass
{
private:
std::string _name;
public:
MyAwesomeClass();
MyAwesomeClass(const std::string& name);
void print_name();
};
The implementation is defined in the DLL or static library, but when using the type MyAwesomeClass, the compiler needs to know at least its structure. Without including the header, the compiler will complain that it doesn't know what type MyAwesomeClass is (ie. undefined class errors).

Resolving Inclusion Ordering

I am working on a codebase that is not my own, that has the following layout:
object.h:
// Objects are defined
// #include "tickets.h" (functions to access the objects)
// An access-handler object is defined
I want to introduce a class that knows about the objects, can be accessed from functions in tickets.h, but can also use the access-handler object. The functions are separate, i.e. class functions that are called in tickets.h do not use the access-handler (I wouldn't know where to start if that weren't the case).
Therefore my class needs to be defined before tickets.h, but some of its functions need to be defined after the access-handler. Is there a way to do this without splitting it up into two header files something like the following:
// Objects are defined
// -- include declaration of class, and definition of functions that tickets.h needs
// #include "tickets.h"
// An access-handler object is defined
// -- include functions of class that need the access-handler
This seems very messy splitting things up like this into two separate files, I was hoping to keep everything contained.
Thanks for any help, I clearly only have a very rudimentary understanding of declarations/definitions in c++.
EDIT: If I use forward declaration and include it before tickets.h (with the class declared in mynewclass.h and functions defined in mynewclass.cc) will mynewclass.cc be able to use objects declared after the inclusion of mynewclass.h? Namely the access-handler object.
EDIT2: Something like this:
object.h:
class obj { // definition }
#include "tickets.h"
class obj_handler {
public void handle { // code }
}
tickets.h:
void do_something(obj o){
communicator.foo();
}
My object (communicator):
class communicator {
public:
void foo() { // code }
void bar() { // use handle() from obj_handler }
}
As you can see, my communicator needs to be used in tickets.h, but can't be defined until after obj_handler. So where should I include it?
If I correctly understand your question - you can use forward declaration to solve this problem. This will allow you to declare some class before defining it's methods. For example:
// this is forward declaration of class A, no definition provided
class A;
class B
{
// uses A
A * a_;
};
// class A definition
class A
{
// may use class B now
B * b_;
};
I'm not quite sure whether I understand this right and don't have enough reputation here yet to make this a comment, so let me try to answer your question this way, please feel free to follow up if I'm guessing wrong:
I believe what you are referring to is an entire class definition, i.e., one including all function definitions within the class declaration. Other than that, it is not very common to see object definitions followed by preprocessor directives. What is typical though is a forward declaration of functions and a class prototype.
So, for example, you could declare in some header.h:
class C
{
public:
void method1(void);
int method2(void);
};
And in some implementation.cpp the definition of the functions like:
void C::method1(void) { /*...*/ }
In the other file preceded in the inclusion chain by your access-handler you then define the other function:
int C::method2(void) { /*...*/ }
What do you mean by access-handler, by the way?
Oh, and your linker likely will yell somewhat at you if you do function definition in a header file.
With regard to your addenda: everywhere you put a forward declaration, loosely speaking, the compiler will insert a copy of the declaration in question, consider it a soft link in the context of file systems. There are negative implications associated with it, like increased duration and the memory load of compilation if you have many forward declarations of the function signature or class. It's impossible to tell whether this will word in your particular situation since only you know the actual code in question. But most likely it would work.
Take a look at these pages:
http://en.wikipedia.org/wiki/Forward_declaration
When can I use a forward declaration?

C++ Basic Class Layout

Learning C++ and see the class laid out like this:
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area () {return (x*y);}
};
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
I know Java and methods(functions) in Java are written within the class. The class looks like a Java interface. I know I can write the class like this:
class CRectangle {
int x, y;
public:
void set_values (int a, int b) {
x = a;
y = b;
};
int area () {return (x*y);}
};
But is there a difference or standard?
There's a difference. When you write the definition of the function within the class definition (case 2), then the function is considered to have been declared inline. This is standard C++.
Usage, is to declare the member functions (Java methods) within the class definition, in a header file (.h), and to define these member functions in a C++ file (.cpp, .cc, or .C, …) This reduces compilation time, when you change the body of a function, only the C++ file has to be compiled, whereas if you change something in the header file, all C++ files that include this header are to be compiled.
It's much cleaner if you only define prototypes in the class definition (which belongs into a header file) and implement the methods in a cpp file.
When you have very small classes doing everything in the class definition might sound easier since everything is at the same place, but as soon as your class grows any developer using it will hate you since he'll have your code between the method prototypes he might look at to find out something (not everyone uses an IDE which shows all available methods!).
However, there is one exception: Template class methods needs to be implemented in the header as they need to be compiled for every specialization of the template.
The usual way is to put the implementation of functions within a separate cpp file, which is not included by other files, just compiled. This way it is easier to manage dependencies.
If the implementation of a function is given within the class definition (as in your 2nd example), this is a hint for the compiler to inline that function (which it may or may not do in the end, depending on e.g. the internals of the function). As a rule of thumb, function bodies longer than a few lines of code are better put into the cpp file, as these are probably not going inlined, however these may include extra dependencies and clutter the class definition.
The exception is template functions, where the bodies need to be in the header too, for the compiler must see them in order to instantiate the template.
I believe that if the method body is inside the class definition, then it is inlined everywhere is it called.
In C++, member functions which are defined in class are implicitly inline, member functions defined outside the class are not.
This affects the linkage of your two examples - the linker will complain about multiple definitions if the first example is #included in multiple source files, whereas the second example will not.
In terms of what's standard/normal:
The first form is used for complex classes, where the implementation of the functions requires extra headers to be pulled in.
The second form is used for simple classes which don't have extra dependencies.
Either form is used for template classes based on developer preference.
There is a slight difference in that functions defined inside the class are automatically inline. The latter definition can be put into a separate file. Otherwise there is no difference nor preference.
Note that we usually don't write semicolons after function definitions (though they are allowed inside a class definition).
void set_values (int a, int b) {
x = a;
y = b;
} // no semicolon here

Template specialization of a single method from a templated class

Always considering that the following header, containing my templated class, is included in at least two .CPP files, this code compiles correctly:
template <class T>
class TClass
{
public:
void doSomething(std::vector<T> * v);
};
template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
// Do something with a vector of a generic T
}
template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
// Do something with a vector of int's
}
But note the inline in the specialization method. It is required to avoid a linker error (in VS2008 is LNK2005) due to the method being defined more then once. I understand this because AFAIK a full template specialization is the same as a simple method definition.
So, how do I remove that inline? The code should not be duplicated in every use of it. I've searched Google, read some questions here in SO and tried many of the suggested solutions but none successfully built (at least not in VS 2008).
Thanks!
As with simple functions you can use declaration and implementation.
Put in your header declaration:
template <>
void TClass<int>::doSomething(std::vector<int> * v);
and put implementation into one of your cpp-files:
template <>
void TClass<int>::doSomething(std::vector<int> * v) {
// Do somtehing with a vector of int's
}
Don't forget to remove inline (I forgot and thought this solution will not work :) ).
Checked on VC++2005
You need to move specialization definition to CPP file.
Specialization of member function of template class is allowed even if function is not declared as template.
There is no reason to remove the keyword inline.
It does not change the meaning of the code in anyway.
If you want to remove the inline for whatever reason the solution of maxim1000 is perfectly valid.
In your comment, though, it seems you believe that the inline keyword means that the function with all his contents gets always inlined but AFAIK that is actually very much dependent on your compiler optimization.
Quoting from the C++ FAQ
There are several ways to designate that a function is inline, some of
which involve the inline keyword, others do not. No matter how you
designate a function as inline, it is a request that the compiler is
allowed to ignore: the compiler might inline-expand some, all, or none
of the places where you call a function designated as inline. (Don’t
get discouraged if that seems hopelessly vague. The flexibility of the
above is actually a huge advantage: it lets the compiler treat large
functions differently from small ones, plus it lets the compiler
generate code that is easy to debug if you select the right compiler
options.)
So, unless you know that that function will actually bloat your executable or unless you want to remove it from the template definition header for other reasons, you can actually leave it where it is without any harm
This is a little OT, but I thought I'd leave this here in case it helps someone else. I was googling about template specialization which led me here, and while #maxim1000's answer is correct and ultimately helped me figure my problems out, I didn't think it was abundantly clear.
My situation is a little different (but similar enough to leave this answer I think) than the OP's. Basically, I'm using a third party library with all different kinds of classes that define "status types". The heart of these types are simply enums, but the classes all inherit from a common (abstract) parent and provide different utility functions, such as operator overloading and a static toString(enum type) function. Each status enum is different from one another and unrelated. For example, one enum has the fields NORMAL, DEGRADED, INOPERABLE, another has AVAILBLE, PENDING, MISSING, etc. My software is in charge of managing different types of statuses for different components. It came about that I wanted to utilize the toString functions for these enum classes, but since they're abstract I couldn't instantiate them directly. I could have extended each class I wanted to use, but ultimately I decided to create a template class, where the typename would be whatever concrete status enum I cared about. Probably some debate can be had about that decision, but I felt like that was a lot less work than extending each abstract enum class with a custom one of my own and implementing the abstract functions. And of course in my code, I just wanted to be able to call .toString(enum type) and have it print the string representation of that enum. Since all the enums were entirely unrelated, they each had their own toString functions that (after some research I learned) had to be called using template specialization. That led me here. Below is an MCVE of what I had to do in order to make this work correctly. And actually my solution was a bit different than #maxim1000's.
This is a (greatly simplified) header file for the enums. In reality, each enum class was defined in it's own file. This file represents the header files that are supplied to me as part of the library I am using:
// file enums.h
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
adding this line just to separate the next file into a different code block:
// file TemplateExample.h
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
// this is the function I was most concerned about. Unlike #maxim1000's
// answer where (s)he declared it outside the class with full template
// parameters, I was able to keep mine declared in the class just like
// this
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
next file
// file TemplateExample.cpp
#include <string>
#include "enums.h"
#include "TemplateExample.h"
// for each enum type, I specify a different toString method, and the
// correct one gets called when I call it on that type.
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
next file
// and finally, main.cpp
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"
int main()
{
TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);
std::cout << t1.toString() << std::endl;
std::cout << t2.toString() << std::endl;
return 0;
}
and this outputs:
BEARS1
TIGERS3
No clue if this is the ideal solution to solve my problem, but it worked for me. Now, no matter how many enumeration types I end up using, all I have to do is add a few lines for the toString method in the .cpp file, and I can use the libraries already-defined toString method without implementing it myself and without extending each enum class I want to use.
I'd like to add that there is still a good reason to keep the inline keyword there if you intend to leave also the specialization in the header file.
"Intuitively, when you fully specialize something, it doesn't depend on a template parameter any more -- so unless you make the specialization inline, you need to put it in a .cpp file instead of a .h or you end up violating the one definition rule..."
Reference: https://stackoverflow.com/a/4445772/1294184