error occurs if output operator is made a template

S

subramanian100in

Consider the foillowing program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

template <typename T>
class TemplateClass
{
public:
explicit TemplateClass(const T& arg = T());
ostream& print(ostream& os) const;

private:
T t;
};

template<typename T>
inline TemplateClass<T>::TemplateClass(const T& arg) : t(arg)
{
}

template <typename T>
inline ostream& TemplateClass<T>::print(ostream& os) const
{
return os << "from TemplateClass<T>::print(): " << t;
}

template <typename T>
inline ostream& operator<<(ostream& os, const T& obj)
{
return obj.print(os);
}

int main()
{
string str("Test string");
TemplateClass<string> obj(str);

cout << obj << endl;

return EXIT_SUCCESS;
}

When I compile this program as
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

I get the following errors:

x.cpp: In member function `std::eek:stream&
TemplateClass<T>::print(std::eek:stream&) const [with T = std::string]':
x.cpp:32: instantiated from `std::eek:stream& operator<<(std::eek:stream&,
const T&) [with T = TemplateClass<std::string>]'
x.cpp:40: instantiated from here
x.cpp:26: error: ambiguous overload for 'operator<<' in 'os << "from
TemplateClass<T>::print(): "'
x.cpp:31: note: std::eek:stream&
operator<<(std::eek:stream&, const T&) [with T = char[33]]

These errors occur because I have made the 'operator<<' a
function template. Is it correct ?

Is it possible to get rid of these compilation errors while keeping
the 'operator<<' a function template ? If so kindly explain with
program sample. If not possible, then we have to write

inline ostream& operator<<(ostream& os,
const SomeSpecificType& obj)
where 'SomeSpecificType' is a explicit class name.
Is this understanding of mine is correct ?

Thanks
V.Subramanian
 
R

Ron AF Greve

Hi,

It tries to find a function ostream.operator<<( TemplateClass .... )

which doesn't exist.

You have to define a friend template function:

Like for instance this (replace with MChannel with ostream and KDTriangleT
with your type and adjust template arguments and implementation
accordingly.:

template ......

template <typename VerticeT, typename FloatT, typename IntT>
friend MChannel& operator<<( MChannel& Channel, const KDTriangleT<VerticeT,
FloatT, IntT>& Triangle );
};

template <typename VerticeT, typename FloatT, typename IntT>
inline MChannel& operator<<( MChannel& Channel, const KDTriangleT<VerticeT,
FloatT, IntT>& Triangle )
{
Channel << "-- Triangle" << endl;
Channel << " " << Triangle.Vertices[ 0 ] << endl;
Channel << " " << Triangle.Vertices[ 1 ] << endl;
Channel << " " << Triangle.Vertices[ 2 ] << endl;
return Channel;
}

| Consider the foillowing program x.cpp:
|
| #include <cstdlib>
| #include <iostream>
| #include <string>
|
| using namespace std;
|
| template <typename T>
| class TemplateClass
| {
| public:
| explicit TemplateClass(const T& arg = T());
| ostream& print(ostream& os) const;
|
| private:
| T t;
| };
|
| template<typename T>
| inline TemplateClass<T>::TemplateClass(const T& arg) : t(arg)
| {
| }
|
| template <typename T>
| inline ostream& TemplateClass<T>::print(ostream& os) const
| {
| return os << "from TemplateClass<T>::print(): " << t;
| }
|
| template <typename T>
| inline ostream& operator<<(ostream& os, const T& obj)
| {
| return obj.print(os);
| }
|
| int main()
| {
| string str("Test string");
| TemplateClass<string> obj(str);
|
| cout << obj << endl;
|
| return EXIT_SUCCESS;
| }
|
| When I compile this program as
| g++ -std=c++98 -pedantic -Wall -Wextra x.cpp
|
| I get the following errors:
|
| x.cpp: In member function `std::eek:stream&
| TemplateClass<T>::print(std::eek:stream&) const [with T = std::string]':
| x.cpp:32: instantiated from `std::eek:stream& operator<<(std::eek:stream&,
| const T&) [with T = TemplateClass<std::string>]'
| x.cpp:40: instantiated from here
| x.cpp:26: error: ambiguous overload for 'operator<<' in 'os << "from
| TemplateClass<T>::print(): "'
| x.cpp:31: note: std::eek:stream&
| operator<<(std::eek:stream&, const T&) [with T = char[33]]
|
| These errors occur because I have made the 'operator<<' a
| function template. Is it correct ?
|
| Is it possible to get rid of these compilation errors while keeping
| the 'operator<<' a function template ? If so kindly explain with
| program sample. If not possible, then we have to write
|
| inline ostream& operator<<(ostream& os,
| const SomeSpecificType& obj)
| where 'SomeSpecificType' is a explicit class name.
| Is this understanding of mine is correct ?
|
| Thanks
| V.Subramanian
|
 
B

Bo Persson

Consider the foillowing program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

template <typename T>
class TemplateClass
{
public:
explicit TemplateClass(const T& arg = T());
ostream& print(ostream& os) const;

private:
T t;
};

template<typename T>
inline TemplateClass<T>::TemplateClass(const T& arg) : t(arg)
{
}

template <typename T>
inline ostream& TemplateClass<T>::print(ostream& os) const
{
return os << "from TemplateClass<T>::print(): " << t;
}

template <typename T>
inline ostream& operator<<(ostream& os, const T& obj)
{
return obj.print(os);
}

This functions is WAY too general, as it matches any type, not just
your type but also int or std::string.

That's what the error message is about - in your print function the

os << "from TemplateClass<T>::print(): "

part matches both your operator<< and the one already defined in the
standard library.


Bo Persson
 
J

James Kanze

It tries to find a function ostream.operator<<( TemplateClass
.... )

Why would it try to do that? His left hand operator is an
std::eek:stream&, not a TemplateClass.
which doesn't exist.
You have to define a friend template function:

Making operator<< a friend is one solution, but not the only
one. His solution works quite well, if he declares the template
correctly, so that it only matches his TemplateClass, and not
everything in the world, e.g.:
template<typename T>
std::eek:stream& operator<<( std::eek:stream const& dest,
TemplateClass said:

And you really shouldn't top post.
 
P

Paul Bibbings

Consider the foillowing program x.cpp:

#include <cstdlib>
#include <iostream>
#include <string>

using namespace std;

template <typename T>
class TemplateClass
{
public:
explicit TemplateClass(const T& arg = T());
ostream& print(ostream& os) const;

private:
T t;
};

template<typename T>
inline TemplateClass<T>::TemplateClass(const T& arg) : t(arg)
{
}

template <typename T>
inline ostream& TemplateClass<T>::print(ostream& os) const
{
return os << "from TemplateClass<T>::print(): " << t;
}

template <typename T>
inline ostream& operator<<(ostream& os, const T& obj)
{
return obj.print(os);
}

int main()
{
string str("Test string");
TemplateClass<string> obj(str);

cout << obj << endl;

return EXIT_SUCCESS;
}

When I compile this program as
g++ -std=c++98 -pedantic -Wall -Wextra x.cpp

I get the following errors:

x.cpp: In member function `std::eek:stream&
TemplateClass<T>::print(std::eek:stream&) const [with T = std::string]':
x.cpp:32: instantiated from `std::eek:stream& operator<<(std::eek:stream&,
const T&) [with T = TemplateClass<std::string>]'
x.cpp:40: instantiated from here
x.cpp:26: error: ambiguous overload for 'operator<<' in 'os << "from
TemplateClass<T>::print(): "'
x.cpp:31: note: std::eek:stream&
operator<<(std::eek:stream&, const T&) [with T = char[33]]

These errors occur because I have made the 'operator<<' a
function template. Is it correct ?

Is it possible to get rid of these compilation errors while keeping
the 'operator<<' a function template ? If so kindly explain with
program sample. If not possible, then we have to write

inline ostream& operator<<(ostream& os,
const SomeSpecificType& obj)
where 'SomeSpecificType' is a explicit class name.
Is this understanding of mine is correct ?


You're missing the solution, which is somewhere in between these two.
Write your op<< as:

template<typename T>
inline ostream& operator<<(ostream& os, const TemplateClass<T>& obj)
{ ^^^^^^^^^^^^^^^^
return obj.print(os);
}

Regards

Paul Bibbings
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top