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.
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 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);
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.
I've looked a lot, tried a bunch of things I found on stackoverflow and other websites but I still can't figure out how to fix this...
Main C++ file : source.cpp
#include "sources.h"
#include "fft_windows.h"
...
source.h
#include "Array2D.h"
...
Array2D.h
#ifndef ARRAY2D_H_
#define ARRAY2D_H_
#include <cassert>
#include "Features.h"
template <class T> class Array2D{
...
};
#endif
Features.h
#ifndef FEATURES_H_
#define FEATURES_H_
#include <string>
using namespace std ;
class Features : public Array2D {
...
};
#endif
fft_window.h (function declarations that are defined in fft_window.cpp)
//#include "Array2D.h"
template <class T>class Array2D;
void random_example(unsigned int i, Array2D <double> &arr);
...
I've tried everything I found and for some reason I still get this error in Features.h on the class Features : public Array2D { line...
Any idea ?
Array2D is not a class. Array2D<int> is, or Array2D<float>
First, Features.h needs to include Array2D.h, second you get an infinite include recursion with that, and third you need to specify the template parameter when inheriting from Array2D:
class Features : public Array2D<int> {
// example --- ^^^
Array2D is declared in Array2D.h file and you are using that template class in Features.h without #include"Array2D.h". Include that file as said and also remove the inclusion of Feature.h to make sure that there is no recursive includes.
Also, Array2D should be used with template argument, like <int>, <char>, <T> and so on.