0

Please have a look at the following code.

Main.cpp

#include <iostream>
#include "Maximum.h"

using namespace std;

int main()
{

    Maximum max;

    int int1, int2, int3;

    cout << "Input three integers: ";
    cin >> int1 >> int2 >> int3;    
    cout << "The maximum value is: " << max.maximum(int1,int2,int3) << endl;




    double double1, double2, double3;

    cout << "Input three doubles: ";
    cin >> double1 >> double2, double3;    
    cout << "The maximum value is: " << max.maximum(double1, double2, double3) << endl;



    char char1, char2, char3;

    cout << "Input three char values: ";
    cin >> char1 >> char2 >> char3;
    cout << "The maximum value is: " << max.maximum(char1,char2,char3) << endl;

}

Maximum.h

template <class T>

class Maximum
{
    public:
        Maximum();
        T maximum(T value1, T value2, T value3);
};

Maximum.cpp

#include  <iostream>
#include "Maximum.h"

Maximum::Maximum()
{

}

    T Maximum::maximum(T value1, T value2, T value3)
    {
         T maximumValue = value1;

        if(value2>maximumValue)
        {
            maximumValue = value2;
        }

        if(value3>maximumValue)
        {
            maximumValue = value3;
        }


        return maximumValue;
    }

In maximum.cpp, it gives "'T' does not name a type" error. Since it is a user defined one, it might not identified it. How to solve this problem?

PeakGen
  • 21,894
  • 86
  • 261
  • 463

5 Answers5

2

Member functions of class templates are themselves templates, and must be defined as such:

template <typename T>   // <-- Add this
Maximum::Maximum()
{
    // code
}

template <typename T>   // <-- Add this
T Maximum::maximum(T value1, T value2, T value3)
{
    // code
}

Once you've fixed that, you'll probably get some linker errors, because templates must (usually) be defined in every translation unit that uses them. The fix is to move the definitions into the header file. See this question for full details.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Thanks for the reply, but why I need to add the template in both the places? – PeakGen Aug 28 '12 at 05:56
  • @Yohan: The language requires that both declarations and definitions of templates are marked as templates. Otherwise, there's no way to declare that `T` is a template parameter, which is why your error said "`T` does not name a type". – Mike Seymour Aug 28 '12 at 10:50
  • Thanks for the reply. I marked this as the answer. However, I believe you didn't understand the question I askes in the comments. What I asked is, there are 2 template in cpp file. There is only one template! The next one is the constructor!! Why is that?? Please help! – PeakGen Aug 28 '12 at 14:57
  • @Yohan: `Maximum` is a class template. As such, all its member functions, including its constructor(s) and destructor, are also templates. – Mike Seymour Aug 28 '12 at 15:04
  • Thanks Mike. That sounds great :) – PeakGen Aug 28 '12 at 16:03
1

In your Maximum.cpp, your constructor and function should be called like this

template <class T>
Maximum<T>::Maximum()
{

}

template <class T>
T Maximum<T>::maximum(T value1, T value2, T value3)
{
        T maximumValue = value1;

    if(value2>maximumValue)
    {
        maximumValue = value2;
    }

    if(value3>maximumValue)
    {
        maximumValue = value3;
    }


    return maximumValue;
}

and in your main function you should call the class this way

 Maximum<int> max;
Caesar
  • 9,483
  • 8
  • 40
  • 66
  • @J.N. The issue is not that T is know or unknown in the .cpp file but that in the header file he declared the class as template class Maximum and so the linker is looking for it is equivalent in the cpp file. – Caesar Aug 25 '12 at 15:18
  • No, the issue is that template code is rarely found in cpp files. A class like this should be entirely in a header file. – J.N. Aug 25 '12 at 15:21
  • @J.N. While I agree with you that it is a bad style, this is not http://codereview.stackexchange.com. – Caesar Aug 25 '12 at 17:18
1

Your understanding of templates is wrong.

First, templates like this need a "user defined" type that is not known before usage. So they can't be found in .cpp files where everything must be known to the compiler (well, actually they can, but let's keep it simple for now).

As a consequence all your template code should be in header files. These header files must be shared with people using your code. For each CPP file in which your template header is included everything will be known and the compilation will be possible.

Then, you are using a class while what you need is a function.

So your final code should be limited to:

Maximum.h.

template<class T>
T Maximum(T v1, T v2, T v3) {
     // code in your member function
}

Main.cpp:

#include <iostream>
#include "Maximum.h"

using namespace std;

int main()
{
    double d1, d2, d3;
    double max = Maximum(d1, d2, d3);

    ...
}
J.N.
  • 8,203
  • 3
  • 29
  • 39
1

First of all to make your code work try this code bellow. I made some changes.

Main.cpp

#include <iostream>
#include "Maximum.h"

using namespace std;

int main()
{

Maximum<char> max; // here you must explicitly specify template argument, I choosed "char"

int int1, int2, int3;

cout << "Input three integers: ";
cin >> int1 >> int2 >> int3;
cout << "The maximum value is: " << max.maximum(int1,int2,int3) << endl;




double double1, double2, double3;

cout << "Input three doubles: ";
cin >> double1 >> double2, double3;
cout << "The maximum value is: " << max.maximum(double1, double2, double3) << endl;



char char1, char2, char3;

cout << "Input three char values: ";
cin >> char1 >> char2 >> char3;
cout << "The maximum value is: " << max.maximum(char1,char2,char3) << endl;

}

Maximum.cpp

#include  <iostream>
#include "Maximum.h"
template <class T> // add this line
Maximum<T>::Maximum()
{

}
template <class T> // you must add this line
T Maximum<T>::maximum(T value1, T value2, T value3) // also here Maximum<T>:: and not Maximum::
{
     T maximumValue = value1;

    if(value2>maximumValue)
    {
        maximumValue = value2;
    }

    if(value3>maximumValue)
    {
        maximumValue = value3;
    }


    return maximumValue;
}

template class Maximum<char>;// you have to explicitly instantiate Maximum<char> for linking time.

You have to know that in Main.cpp there is no definition of the class template Maximum so even thou you called Maximum<char> no definition will be generated, because your class template definition of Maximum is inside Maximum.cpp. and because you didn't use MAximum<char> inside Maximum.cpp no definition will be generated inside Maximum.cpp for the linking time. for this reason you have to explicitly instantiate Maximum<char> for the linking time.

AlexDan
  • 3,203
  • 7
  • 30
  • 46
  • You should instantiate `Maximum` and `Maximum` as well, though, it would be preferable to move everything to the header and let the compile instantiate only what's needed on demand. Use a function made for `char` to compare double will probably be surprising at times. – J.N. Aug 28 '12 at 14:22
1

First, copy the code from maximum.cpp to the end of maximum.h, then remove maximum.cpp. The compiler has to see the code wherever the template is used, so template code should almost always be in the header where the template is defined.

Second, mark the definitions of the member functions (the code that you just copied) as templates:

template <class T>
Maximum<T>::Maximum() { }

etc.

Third, note that constructors cannot return values; the return statement in Maximum::Maximum(T value1, T value2, T value3) is illegal. Add a data element of type T and store the result there; then add an accessor so that users of this class can get the stored value.

Or follow the suggestion made in another answer and make this a function. That's a much better solution.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165