I have a template class myClass prototyped in a header file, and am implementing it in a .cpp file that is included at the end of the header file. When I use the code:
template<typename T>
class myClass {
public:
void myFunction(const T item);
};
in the header file and
template <class T>
void myClass<T>::myFunction(const T item)
{
//stuff
}
in the implementation file, I get the above error on line 2 of the implementation code. I have used this same exact syntax in another program with successful compilation and correctly functioning results, so I am quite confused. There are three different function definitions in the .cpp file and all have this same error on their respective lines. I assume I am making a small error but I really can't seem to figure it out.
Help and explanation are very much appreciated.
EDIT:
Here is an SSCCE which has the same error:
main.cpp
#include <iostream>
#include "myClass.h"
using namespace std;
int main(){
myClass<int> example;
example.myFunction(1);
return 0;
}
myClass.h
#include<iostream>
#ifndef MYCLASS_H_
#define MYCLASS_H_
template<typename T>
class myClass {
public:
void myFunction(const T item);
};
#include "myClass.cpp"
#endif /* MYCLASS_H_ */
myClass.cpp
using namespace std;
template <class T>
void myClass<T>::myFunction(const T item)
{
cout << "Hello World!";
}
and I am using Code::Blocks 10.05 with the GNU GCC compiler.
I finally solved the problem by removing the myClass.cpp from the build configuration. Not sure why this was necessary, but it works perfectly now.
Put the implementation of the method in the header file (.h) too
The compiler needs to know details of implementation in translation unit.
It is very difficult to declare a template in an .h file and define it in a .cpp file. The compiler needs template declaration and definition in a single file in order to create the code. So if your compiler does not support export keyword it won't work.
So you should not use different files for declaration and definition. See also this thread.
Templates are instantiated on demand and given the complexities which would be induced in compiler design most of the compilers build a restriction to keep the template declaration and definition in one single file. If not so, template declaration on top of class and function definitions would create a pattern difficult for the compiler to detect a pattern and instantiate the template.
Similar question has been discussed on Stackoverflow, and explained on Parashift and cplusplus.com (Read: Templates and multiple-file projects at the end of the article).
Hope this helps!
Vivek
Keep implementation in myClass.cpp file is also possible. Apart from the implementation itself, you need to put declarations with specific types of T. For example, if T could be int and float, myClass.cpp should be like:
using namespace std;
template <class T>
void myClass<T>::myFunction(const T item)
{
cout << "Hello World!";
}
// Declarations with specific types.
template void myClass<int>::myFunction(const int item);
template void myClass<float>::myFunction(const float item);
Related
I want to separate .h and .cpp for template class.
Here is the what I was doing:
I wrote directly .h and .cpp like without template. So it creates an exception like Link 2019 Template exception
There are some solution to handle this How to define template class header and implement it in another cpp. I choose solution 3.
According to the solution I added include *.cpp just before #endif inside header.(Still *.cpp includes *.h)(Below code represents this step) It gives
template has already been defined error.
According to research the way of get rid of this error is(circular dependency) remove #include *.h from *.cpp but this time
unrecognizable template declaration/definition error
Occured. My question is if I include *.cpp to *.h file. How can we build project as expected? Or this solution is obsolute?
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template<class T>
class TestTemp
{
public:
TestTemp();
void SetValue(T obj_i);
T Getalue();
private:
T m_Obj;
};
#include "TestTemp.cpp"
#endif
// TestTemp.cpp
#include "TestTemp.h"
template <class T>
TestTemp<T>::TestTemp()
{
}
template <class T>
void TestTemp<T>::SetValue(T obj_i)
{
}
template <class T>
T TestTemp<T>::Getalue()
{
return m_Obj;
}
#include "TestTemp.h"
int main()
{
TestTemp<int> a;
a.Getalue();
return 0;
}
Unlike member functions of ordinary classes, member functions of template classes cannot be compiled separately and linked into the executable. The members of a template must be visible to the compiler at the point where they're used. That's what all that nonsensical include stuff in that horrible article is about.
The simplest way to do this is to put the definitions directly into the template definition:
#ifndef TEST_H
#define TEST_H
template <class Ty>
class test {
public:
void f() { /* whatever */ }
};
#endif
This has the drawback that larger classes become unreadable (cf. Java). So the next step is to move the definitions outside the template, but keep them in the header:
#ifndef TEST_H
#define TEST_H
template <class Ty>
class test {
public:
void f();
};
template <class Ty>
void test<Ty>::f() { /* whatever */ }
#endif
Many people feel that that's still too cluttered, and want to put the definitions into a separate file. That's okay, too, but you have to make sure that that separate file gets included whenever the original header is used:
#ifndef TEST_H
#define TEST_H
template <class Ty>
class test {
public:
void f();
};
#include "test.imp"
#endif
This is the file "test.imp":
#ifndef TEST_IMP
#define TEST_IMP
template <class Ty>
void test<Ty>::f() { /* whatever */ }
#endif
Note that "test.imp" is really a header file, so it gets into your code through the #include "test.imp" directive in test.h. It cannot be compiled separately, so should not be named with a .cpp extension, which would, at best, be misleading.
I am new to C++, I have a very simple program but it can't be compiled.
Darray.h
#ifdef DARRAY_H
#define DARRAY_H
namespace myspace{
template<class T>
class DynamicTypeArray{
public:
DynamicTypeArray();
private:
int length;
};
}
#endif
Darray.cpp
#include "Darray.h"
namespace myspace{
template <class T>
DynamicTypeArray<T>::DynamicTypeArray(){
length = 0;
}
}
I think it is pretty straightforward, but when I try to compile it with
g++ Darray.cpp
it gives me an error
unknown type name 'DynamicTypeArray'
Am I doing anything wrong here? The problem drives me crazy right now.
Thank you
C++ templates are built in a way that (afaik) you can't have template class split over header (.h) and implementation (.cpp) files.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get “unresolved external symbol” errors when using templates?
“undefined reference” to a template class function
I got error on line: Console::getInstance()->readObjectData(a); in main.cpp
undefined reference to void Console::readObjectData<std::string>std::string&)
Console.h
http://pastebin.com/WsQR7JNq
#define CONSOLE_H
#include <string>
using namespace std;
class Console
{
public:
static Console* getInstance();
template <typename T>
void readObjectData(T& o);
protected:
private:
Console(); // Private so that it can not be called
Console(Console const&); // copy constructor is private
Console& operator=(Console const&); // assignment operator is private
static Console* m_pInstance;
};
#endif // CONSOLE_H
Console.cpp
http://pastebin.com/N02HjgBw
#include "Console.h"
#include "Log.h"
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
// Global static pointer used to ensure a single instance of the class.
Console* Console::m_pInstance = NULL;
Console::Console()
{
}
Console::Console(Console const&)
{
}
Console& Console::operator=(Console const&)
{
}
Console* Console::getInstance()
{
if (!m_pInstance) // Only allow one instance of class to be generated.
m_pInstance = new Console;
return m_pInstance;
}
template <typename T>
void Console::readObjectData(T& o) {
//cin >> o;
}
main.cpp
http://pastebin.com/U6qAJUN1
#include "Console.h"
using namespace std;
int main()
{
string a;
Console::getInstance()->readObjectData(a);
return 0;
}
any ideas?
You cannot define template<>'d function in .cpp file.
Move
template <typename T>
void Console::readObjectData(T& o) {
//cin >> o;
}
To header file.
You did not implemented this method. You have to provide implementation for your template in .h file
Because you've not put the implementation of readObjectData in the header, you will need to provide an explicit specialization of the function - one that takes std::string&.
This should go in Console.cpp:
template <>
void Console::readObjectData(string& o) {
//cin >> o;
}
You cannot place your template method implementation in Console.cpp it must appear in the header file, or you must implement an explicit specialization for std::string.
The definition for the templated function (readObjectData) has to be inlined, not in a .cpp file.
The compiler when it see's a class with a templated function, or a templated class, makes a copy of the entire class with the new type stuck in there. So if you stick the definition of the function in the .cpp file, the compiler will not know where the implementation is because it doesn't exist.
In the process of converting some C++ files to the output( executive, shared library or ... ) 2 tools will co-operate, first compiler that create object files and then linker that convert those objects to the output. What you should know is that linker has nothing to do with template( except in special case of explicit instantiation ), and templates will be instantiated by compiler and another note is compiler work with each source files and headers that included in that source file and ignore all other files of your project. So when compiler want to compile main.cpp it see no implementation of readObjectData and thus it can't generate any code in the object files for that function, and when linker want to link objects to result it will never find an implementation for that function! So the easiest way is to move your implementation of readObjectData to the .h file and every thing will work as expected.
I have the following simple template code:
#ifndef CLUSTER_H
#define CLUSTER_H
#include <iostream>
#include <vector>
template <typename T, size_t K>
class Cluster
{
public:
void Print() const;
private:
std::vector<T> objects;
};
template <typename T, size_t K>
void Cluster<T,K>::Print() const
{
for (int i=0; i<objects.size(); i++)
{
T curr=objects[i];
std::cout << curr << " ";
}
std::cout << std::endl;
}
#endif
and for some reason I get the following error: "undefined reference to 'Cluster<int, 5u>::Print() const'. What could be the cause for this?
Thanks!
So, I'm going to go out on a limb here and say that you've defined a template function in a CPP file, which means it will end up in a different translation unit. Here's a simple example:
A header, example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
template<int TValue>
class example
{
public:
int get_tvalue();
};
#endif
A source file, example.cpp
#include "example.h"
template<int TValue>
int example<TValue>::get_tvalue()
{
return TValue;
}
And another source file, main.cpp
#include "example.h"
int main()
{
example<5> instance;
instance.get_tvalue();
return 0;
}
If I compile these together using GCC, I get undefined reference to 'example<5>::get_tvalue()'. This is because of the way template classes are instantiated. A template class definition is just that... a template, not an actual class. The actual class definition is created when a parameterised (or specifically, fully specialised) definition of that class occurs, in this case, example<5>. That fully specialised class definition only exists in main.cpp... there's no such class inside example.cpp! Example.cpp contains only the template, and no specialisations. This means the function, get_tvalue is not defined for example<5> in main.cpp, hence the error.
You can fix this in one of two ways. The first way is to always have your entire template class defined in its header file. This is the way its done with STL containers, for example. The alternative is to force creation of a parameterised class in example.cpp... you can do this by adding
template class example<5>;
to the end of example.cpp. Because there's now an actual class definition for example<5> in example.cpp, you will also get an actual function definition for example<5>::get_tvalue and when your translation units main.o and example.o are linked together at the end of the compilation step everything will be fine.
Obviously, this would be a poor approach in most cases, but under circumstances where your template parameters take only a small range of values it can work. Putting your whole class in the header file is probably easiest, safest and most flexible though.
I'm having trouble with compiling my template class. This is my list.cpp
using namespace std;
template <class T>
List<T>::List()
{
length = 0;
}
template <class T>
List<T>::~List()
{
}
template <class T>
List<T> & List<T>::operator=(const List<T> & rhs)
{
List<T> hha;
return hha;
}
template <class T>
int List<T>::size()
{
return length;
}
ANd this is my list.h
#ifndef _LIST_H_
#define _LIST_H_
#include <iterator>
#include <ostream>
using namespace std;
template <class T>
class List
{
private:
class ListNode
{
public:
ListNode();
ListNode(const T element);
ListNode *next;
T data;
};
public:
// big3
List();
~List();
List<T> & operator=(const List<T> & rhs);
int size();
bool empty();
void print(ostream & os) const;
private:
ListNode * head;
ListNode * tail;
int length;
};
#include "list.cpp"
#endif
when I run g++ list.cpp
I get errors
expected constructor, destructor, or type conversion before ‘<’ token
for definitions of constructor, destructor, and operator...
I don't know what seems to be wrong
The template implementation goes in the header.
It is a bit of a hack but it is how it is done.
The problem you currently encounter is that you list.cpp doesn't include you list.h: the compiler sees a couple of definitions for things which aren't declared, yet. You can fix this problem by including list.h at the top of your file:
#include "list.h"
...
However, this will essentially lead to a problem coming: if you actually want to use your List<T> with some type, the compiler will need to see the template definition where the class template is used. That is, typically you will implement your templates in the header file. The alterntaive is to implement templates in an implementation file and explicitly instantiating the types it is to be used with. This is quite reasonable for some templates but for something intended to be used for an unknown number of types this isn't practical.
BTW, you are using names which you are not allowed to touch: names starting with an underscore followed by a capital letter are reserved for the C++ implementation, i.e. the compiler and the standard library. Names using two consecutive underscores anywhere are also reserved.
Since list.hpp doesn't get #included in list.cpp, the compiler doesn't know about the template definition in that header when you try to compile list.cpp.
You compile list.cpp, that defines your list member functions. But it doesn't contain the template class declaration - that is in the header.
I see you include cpp in your list header. This will sort of work if you include the list header in some other cpp file and make sure list.cpp will not be compiled as a separate compilation unit.
What I mean is i.e. file main.cpp:
#include "list.h"
int main()
{}
Then compile this with g++ main.cpp.
Usually you just want to avoid cpp files when using templates altogether. Just stuff everything in the header and include that. Or alternatively I would at least rename your list.cpp to list.impl or some other name. This way one might be less tempted to actually try to compile that file directly.