June
June

Reputation: 55

C++ using class templates

I have this template class

MyTemplates.h

#ifndef MYTEMPLATES_H
#define MYTEMPLATES_H
#include <iostream>
#include "Main.h"

template <class T>
class myTemplates
{

T difference(T,T);
};

template <class T>
T myTemplates<T>::difference(T a,T b) 
{
return t ((a.getX() - b.getX()),(a.getY() - b.getY()) );
}

Main.cpp

Point p_a (2, 8);
Point p_b (5, 10);
cout << endl;
cout << "difference (p_a, p_b) returns a point with value : ";
p = difference (p_a, p_b);
cout << p << endl << endl;

When i run this, i will get the error called, "differences were not declared in this scope". What i'm trying to do here is to pass two objects into the template and returns the differences in value. in my point class, i have a ostream operator that display the x and y ordinates

Upvotes: 1

Views: 143

Answers (4)

benjarobin
benjarobin

Reputation: 4488

This answer is no longer relevant since the question has been edited

Template class used by another .cpp file cannot be put in a .cpp file.

The compiler doesn't know the type of T when compiling the .cpp. You must put everything that use the type T inside the .h

This is fine if you put everything (the class and the implementation) into the .cpp file, if this template class is used only in this .cpp file.

Upvotes: 1

Mike Seymour
Mike Seymour

Reputation: 254431

You've made difference a member of a class template, even though it doesn't logically belong to a class. You should make it a free function template:

template <class T>
T difference(T a,T b) 
{
    // whatever
}

and then your code in main should work as you expect - the template parameter will be inferred from the function argument types.

If you did want it to be a class member, then you'll need an object to call it on:

p = myTemplates<Point>().difference(p_a, p_b);

but that's clearly not what you want here.

Upvotes: 3

risingDarkness
risingDarkness

Reputation: 708

The compiler needs a complete definition of a template to be able to instanciate it.

You have 2 translation units: myTemplates.cpp and Main.cpp. When compiling myTemplates.cpp actually nothing happens, because it's a template definition with no instantiation.

Then you compile Main.cpp and want to instanciate myTemplate, but this is not possible, because the definition of your template in myTemplates.h is not complete: a part of the template definition is in myTemplates.cpp and the compiler already forgot about that one ;)

To solve your problem you need to put the complete template definition into myTemplates.h and as myTemplates.cpp is then empty, you can get rid of it.

As your Main.cpp you posted is incomplete and you still get the error: don't forget to include myTemplates.h in your Main.cpp.

Upvotes: 0

Manu343726
Manu343726

Reputation: 14174

C and C++ compiles each sorce file is its own "translation unit". A translation unit is the sum of the sourcecode of the .cpp file and all files #included on it. So when you compile foo.cpp and bar.cpp, the compiler compiles each cpp file as if it was a hole independient program.

C++ templates compiles in two phases:

  • Declaration: The compiler parses the template declaration, checking its syntax and semantic correctness. Every statement dependent of a template argumment is not parsed here, is parsed in the second phase.

  • Instantation: For each template instantation, the compiler subsitutes the template parametes of the template with the type specified by the instantation, and parses the resulting sourcecode.

The problem with .cpp files is the compiler parses by translation units, but the header and the .cpp file are compiled in different translation units. It should execute the two phases of template parsing in the same translation unit (It needs the result of the first phase to execute the second phase), so when you use a template in the .cpp, the compiler does not know the result of the first phase, which was executed in the header file.

Upvotes: 0

Related Questions