I try to make a generic function in C++, that creating an array of a type which depends on usage (when calling it), like array of int or char.
This is the code in my header file:
template<class T>
T** makeArray(...);
This is in the .cpp file:
template<class T>
T** ClassA::makeArray(...){
//...
}
And this is how I call it in the main file:
char** charArr = cg.makeArray<char>(...);
//...
int** intArr = cg.makeArray<int>(...);
But when compiling, I get these errors:
undefined reference to `char** ClassA::makeArray<char>( ...
undefined reference to `int** ClassA::makeArray<int>( ...
What do the errors mean and how do I fix it?
You have to include the entire body of a C++ template function in the header.
This is because of the way that C++ templates work: template parameter substitution happens only when you actually use the template, and the entire template definition has to be visible at that time. Another way of looking at it is to say that you cannot compile and link to a templateFunction<T>—you can only compile a template function once it's been instantiated as a templateFunction<char> or whatever. For this reason, you cannot put template function definitions in .cpp files, but rather have to put them in .h files.
The compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template, so you need to move the definitions of the functions to your header.
This is called the inclusion model. Also read this FAQ
In general, you cannot have template definitions in a source file; they should be in the header file so that the compiler can see them.
This comes up over and over again here, so I can't be bothered to give the full explanation again; I recommend you read this from the C++ FAQ: Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
[Incidentally, why are you returning a pointer-to-pointer? A pointer should be enough...]
If your code is using the template on a diferent cpp file, the template should go on the header file.
Related
I am reading caffe code and find it split C++ class Template code into hpp and cpp files. For example, Net.cpp includes the template class Net implementation code and Net.hpp includes the definition. But I remembered it is not possible to split a template class into hpp and cpp files, how does caffe make this work?
Thank you.
As you noted, template definitions cannot be split up as easily from the declarations without jumping through some hoops.
One common pattern is to split them up in different files for the human reader but essentially they are still defined all in one header. For example
Foo.h
#pragma once
template <typename T>
void Foo(); // declaration
#include "Foo.inl"
Foo.inl
template <typename T>
void Foo()
{
// actual definition
}
Notice that the last thing in the .h file is to actually include the full contents of the .inl file. As far as the compiler is concerned, all of the template definitions are contained in the header to solve the initial problem you mentioned. But to the human reader, the declarations and definitions are separated.
you can not "usually" separate the template definition and deceleration. when the compiler instantiate the template it need to know exactly the definition and the declaration of the members that are used in the context. so if you only include the header file the compiler doesn't know how to instantiate the template for the template parameter.
A solution other than the one that coryKramer mentioned is after the full definition (in the .cpp file) explicitly instantiate the template for the template parameters that you need, this way the template is already instantiated for the values that you would like to use (at this point we have the full declration and definition of template). However, note that if the template is need to be instantiated for other values you may encounter errors as compiler doesn't know how to do this process if the template is not fully defined in that file!
This is the method that is used in caffe via INSTANTIATE_CLASS(Net) macro at the end of .cpp file.
When we make a class we declare its functions in a header files and define them in a source file... then the header file can be included in the main file to use the class...
But if we declare a template class in header files and define it in the .cpp file and then if we include the header file in the main(containing int main) file then why does a linker error crop up... and the error does not crop up if we included the .cpp file(containing the header file ) in the main file... any answers plz?
Templates don't actually produce any object code at the point where the compiler reads their source code; they're (typically) only "instantiated" when something actually uses the template. So if you define a template function in one source file, and call it from another, the code for the template function doesn't get compiled at all: it's not in the first object file since nothing there needed it, and it's not in the second object file since the compiler didn't have access to the function's definition.
You define template functions in header files so that in each translation unit where something calls the template function, the compiler has access to its code and can compile a copy of it specialized with the appropriate template arguments.
Alternatively, you can use explicit instantiation: you define the template function in a .cpp file, and also tell the compiler exactly which types that it should compile the function for. This is harder to maintain, because you have to keep track of which instantiations are needed by the rest of the program. If something calls foo<float>(), but you've only explicitly instantiated foo<int>() and foo<char>(), you get a missing-symbol error.
You shouldn't #include a .cpp file from another .cpp file. Just put the template function definitions in the header together with their declarations.
A template is neither a class nor a function. Its a pattern that compiler uses to generate classes or functions.
Very nicely explained in HERE
The compiler says it can't find the reference for the function when I do this:
// link.h
template <class T>
T *Link(T *&, T *(*)())
// link.cpp
template <class T>
T c:Link(T *&ChildNodeReference, T *(*ObjectCreator)()){
}
If I implement inside the class on the header it goes smoothly.
Please, I will work on the header until someone enlightens me about this.
There are somethings in C++ that are weirdly annoying. I know, there is a reason for this and etc. Even so, can't the compilers help you out about it -_-"
Templates are essentially semi-type-safe macros, hence the limitation.
Normal (non-template) functions can be compiled to native code residing object/library files, and then referenced with only a prototype available in the header, solely because there's only a single version of such a function.
With templates, C++ compiler has to compile each instantiation of the function separately. Obviously, it cannot do it "in advance", because the set of types for which you can instantiate the function is effectively unbounded (you can always define a new type in your code before calling the function). In fact, two instantiations of the same function template can be completely different. Consider this extreme case:
struct t1 {
template <int>
struct a {};
};
struct t2 {
enum { a = 123 };
};
enum { b = 456, c = 789 };
template <class T>
void foo() {
T::a<b>c;
}
Now if we call foo<t1>(), the statement inside it is a local variable declaration, because t1::a is a class template:
T::a<b> c;
But if we call foo<t2>(), the statement inside is an expression, because t2::a is an integral constant:
(T::a < b) > c;
This is just to show that compiler cannot meaningfully "compile" a template; it really has to mostly preserve the tokens.
Now, all that said, ISO C++ does actually provide the ability to separate declaration and definition of templates, so that they can be treated as normal functions, with declarations in .h files, and definitions in .cpp files. This is called "export templates", because you have to precede both declaration and definiton with keyword export:
// link.h
export template <class T>
T *Link(T *&, T *(*)());
// link.cpp
export template <class T>
T *Link(T *&ChildNodeReference, T *(*ObjectCreator)()) {
}
This is, however, a controversial feature of the Standard because of very high burden on implementation, and most popular implementations refuse to implement it; notably, g++, MSVC, and C++Builder do not implement it. The only compiler I know of that supports it is Comeau C++.
Programming non-template code or non-inlined functions in headers is a Bad Thing™. The reason you have cpp files is to prevent redefinition of the same function code more than once, amongst other things.
The difference with templates is that the compiler practically doesn't touch them until your code instantiates a specialisation of that template which is why they need to have their source inside the header.
When the compiler finds an instantiation of a template specialisation (say List<int>), it goes back to the included template code and compiles it with that specialisation, which is why you don't have issues with redefinition of function code.
What you don't seem to understand is that this doesn't apply to non-templated code. All non-template code is compiled as normal and thus CPP files are needed to only define the code once then link it all together.
If you define functions inside a header, your linker will not link the compiled translation units because they have defined the same function more than once.
Templated implementations (not only definitions) have to be available at compile time.
So, the full template code is normally put in the header file.
Template code must be in the header. Sorry, I completely missed that! (and I thought I'd been coding C++ for years :P)
You forgot the * for the return type. So implementation is not matching definition. Add it and it should work:
T *c:Link(T *&ChildNodeReference, T *(*ObjectCreator)())
{
}
Implementation must be too in the header file under the class definition in order to be available at compile time.
I have a problem I don't really understand. I have a class Node.
template<class T>
class node {
protected:
T _data;
public:
node(T data);
};
This is in "node.h" file. In "node.cpp" file, there is this constructor:
#include "node.h"
template<class T>
node<T>::node (T data) {
_data = data;
}
While the compiler finds no error, the linker (ld) tells me:
/usr/bin/ld: Undefined symbols:
node<int>::node(int)
the weird part... if I move the constructor from .cpp to .h file, everything works fine. Where is the problem?
The problem is that templates aren't classes - you don't normally write them in two separate files. Template classes are code that the compiler uses to generate classes. As such, your implementation code needs to effectively be inline, i.e., in the header as you discovered.
For a fuller explanation of why it has to be this way, see the C++ FAQ Lite.
As a general rule, you must put all template members inside of the header file. Templates are compiled in an as-used basis, and hence the entire definition needs to be available wherever they are used. Putting the code in the header file will solve that problem.
The only time you can put a template definition in a CPP file is when the template will only be used within that CPP file. The reason being is that it meets the standard that the entire definition is available for compilation.
Moving the contents of node.cpp to node.h will fix the problem.
Strange Scenarios
Then again, you can also put everything in a CPP file and include the CPP file. C++ is flexible in this way. I only mention this because I've seen in done before. I actually bruised my jaw when it hit the top of my desk.
When you use node<int>, you have not most likely included node.cpp. Therefore the compiler cannot instantiate the node<int>::node<int> constructor. Usually you put all the template code, including all the implementations of the methods, in the header file, or something included from it.
The commonly accepted practice is to put all of the implementation in the .h file, so that the classes can be generated from the template as needed.
If you know ahead of time which types your template will be instantiated with, you might be able to cheat a little. Just make sure your .cpp includes a use case for each type and method you will need. It is important that the use case come after the template code. E.g. for "node.cpp", use
#include "node.h"
template<class T>
node<T>::node (T data) {
_data = data;
}
void dummy(void)
{
node<int> intnode(0);
node<double> doublenode(0.0);
}
// You can put templates declaration in header and definition in source
// node.h or wherever you include file gets included
extern template class node<int>;
// node.cpp or where ever source file you want to use it
// But use it only once for each type of generated class
template class node<int>;
Unless there's a call to the function, the compiler won't output any code and the linker won't find it.
You should put the function in the header where it belongs.
implicit instantiation is turned off, you need
template class node<int>;
somewhere in your code (node.cpp maybe)
EDIT: bad answer, it's probably not the case.
I have a function declared like so:
template <typename T>
T read();
and defined like so:
template <typename T>
T packetreader::read() {
offset += sizeof(T);
return *(T*)(buf+offset-sizeof(T));
}
However, when I try to use it in my main() function:
packetreader reader;
reader.read<int>();
I get the following error from g++:
g++ -o main main.o packet.o
main.o: In function `main':
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()'
collect2: ld returned 1 exit status
make: *** [main] Error 1
Can anyone point me into the right direction?
You need to use the export keyword. However, I don't think G++ has proper support, so you need to include the template function's definition in the header so the translation unit can use it. This is because the <int> 'version' of the template hasn't been created, only the <typename T> 'version.'
An easy way is to #include the .cpp file. However, this can cause problems, e.g. when other functions are in the .cpp file. It will also likely increase the compile time.
A clean way is to move your template functions into its own .cpp file, and include that in the header or use the export keyword and compile it separately.
More information on why you should try and put template function definitions in its header file (and ignore export altogether).
The problem is that a function template is not a function. It's a template for creating functions as needed.
So for a template to work, the compiler intuitively needs two pieces of information: The template itself, and the type that should be substituted into it.
This is unlike a function call, which the compiler can generate as soon as it knows that the function exists. It doesn't need to know what the function does, just that it looks like void Frobnicate(int, float), or whatever its signature is.
When you declare the function template without defining it, you're only telling the compiler that such a template exists, but not what it looks like. That's not enough for the compiler to be able to instantiate it, it has to be able to see the full definition as well. The usual solution is to put the entire template in a header that can be included where needed.
The best practice with template functions is to define them in header files. They are created at compile time so compiler has to have definition around to do so.
When export for templates would be more supported this wouldn't be the case though but right now it still hardly can be used.
Is their any compiler support template separate compilation?
As I know the common practice is declare and implement template functions in the header file