Why wont this work

If I have this in a regular main.cpp file without adding the separate class file I can get the program to run but I cant get it to work when they are in separate file, why?

(main.cpp)
#include "Math.h"
#include <iostream>
using namespace std;

int main()
{
Math<int> BO(23,56);
cout << BO.addition() << endl;
}

(Math.h)
#ifndef __Calculator__Math__
#define __Calculator__Math__

#include <iostream>
using namespace std;

template <class T>

class Math{

public:
Math(T a, T b){
Num1 = a;
Num2 = b;
}

T addition();
private:
T Num1;
T Num2;
};

#endif /* defined(__Calculator__Math__) */

(Math.cpp)

#include "Math.h"
#include <iostream>
using namespace std;

template <class T>

T Math<T>::addition()
{
return(Num1 + Num2);
}
Simple- Templates, by design, require the declaration and implementation to be in the same file. In other words- a template class cannot have a header and implementation as two different files- they must be the same. This is mostly because templates can do some weird things with the right use- you can have template code that runs while it compiles instead of when the code itself runs, for example. Doesn't work too well with split-files.
temp.h
1
2
3
4
5
6
7
8

template <typename T>
class Foo
{
public:
    void doSomething(T param);
    void normalfunction();
};

temp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename T>
void Foo<T>::doSomething(T param)
{
    qDebug() << param;
}
template <typename T>
void Foo<T>::normalfunction()
{
   qDebug() <<"normal function";

}
//initializer list
template class Foo <int>;
template class Foo <QString>;
template class Foo <ClassX>;

btw i'm using the QT libs

you need an initializer list

This code works,
but breaks down code completion, so I stick to inline declaration.

I think of using an innerclass in a class + referring to it with a pointer.
http://www.w-uh.com/posts/030126-C++_classes.html
Thank You guys for clearing that up, so just to be sure when making templates they should be in the same file unless im using pointers?
Yep. And an initializer list.
Last edited on
How would I go about placing templates in separate files, would I have to get rid of the header file and just use the .cpp then I could call it from main?
No. Headers are included, sources compiled.

When you compile "main.cpp", the compiler does not see verbatim
1
2
3
4
5
6
7
8
9
#include "Math.h"
#include <iostream>
using namespace std;

int main()
{
  Math<int> BO(23,56);
  cout << BO.addition() << endl;
}

The preprocessor did see that file, but did insert each #include, recursively. Therefore, the compiler did see:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// contents of header "iostream" and whatever it includes,
// because the Math.h has #include

using namespace std;

template <class T>
class Math{
public:
  Math(T a, T b){
    Num1 = a;
    Num2 = b;
  }

  T addition();
private:
  T Num1;
  T Num2;
};

// main.cpp had include iostream here, but if iostream has
// include guards, nothing is added here because it has
// already been inserted earlier

using namespace std;

int main()
{
  Math<int> BO(23,56);
  cout << BO.addition() << endl;
}

Line 29 calls Math<int>::addition(). If that would be a concrete function, then compiler would assume that the object file of some other compilation unit has the compiled code for it and the linker will handle it.

However, there exists only template for the function and the compiler should form the source of Math<int>::addition() from template and then compile it. Alas, there is no template in this compilation unit.


You don't have to write the template implementations directly into the header. You can have them in separate file and let the header include it:
1
2
3
4
5
6
7
8
#ifndef unique-foo-header-id
#define unique-foo-header-id
template <typename T>
T foo( T );

#include "foo_impl"

#endif // unique-foo-header-id 

You can name the foo_impl as you wish, but:
* Extension .cpp would hint that it is separately compiled, which it is not
* Extension .h is quite good, maybe you wish to clearly separate implementations from regular headers
* Development environment may or may not be confused by everything else (like .hpp or .icc)
Topic archived. No new replies allowed.