Problems of overloading template operator >>

H

hall

Hi all.

I have run into a problem of overloading a templatized operator>> by a
specialized version of it. In short (complete code below), I have
written a stream class, STR, which defines a templatized operator>>() as
a member that can deal with the built in C types (int, char, float...)

template <class tType> STR& STR::eek:perator>>(tType & t);

I then attempted to add an overloaded version of this to support my own
class, Array3d (a template class), and wrote this as a friend of Array3d as

template <class tType>
STR & operator >> ( STR & outf, Array3d<tType> & array ){}

It all compiles, but when I run the program, the lines;

str << array // str is an STR, array is an Array3d<int>

it will call STR::eek:perator>> <Array3d<int> >, rather than (what I
belived to be) the specialized operator>>(STR &, Array3d<int> &).

If I instead remove the STR::eek:perator>>() and replace it by a friend
function (commented out in the code below) the function call works as i
expect it to.

Can you please enlighten me as to where I have gone wrong?

Best regards
hall




// main.cpp
//---------------------------------------------------------------------------
#pragma hdrstop
#include "IOFile_mod.h"
#include <iostream>

#pragma argsused
int main(int argc, char* argv[])
{
Array3d<int> array;
std::cout << "Operator << for Array3d\n";
STR in;
in >> array;

std::cout << "Operator << for int\n";
int i(3);
in >> i;

return 0;
}
//---------------------------------------------------------------------------



// IOFile_mod.h
//---------------------------------------------------------------------------
#ifndef IOFileH
#define IOFileH

#include <iostream>

// --------------------------------------
class STR
{
public:
template <class tType> STR& operator>>( tType & );
//template <class tType> friend STR & operator >> ( STR & of, tType
& a );
};

template <class tType>
STR& STR::eek:perator>>( tType & obj)
{
std::cout << "STR::eek:perator<<(const tType obj)\n";
return *this;
}

//template <class tType>
//STR & operator >> ( STR & of, tType & a ){
// std::cout << "Friend of STR\n";
// return of;
//}

// --------------------------------------
template <class tType> class Array3d;
template <class tType> STR & operator >> ( STR & of, Array3d<tType> & a );

template <class tType> class Array3d
{
public:
friend STR & operator >> <>( STR & of, Array3d<tType> & a );
};

template <class tType>
STR & operator >> ( STR & outf, Array3d<tType> & array )
{
std::cout << "STR & operator >> (STR & inf, Array3d<tType> & array )\n";
return outf;
}

#endif
//---------------------------------------------------------------------------
 
V

Victor Bazarov

hall said:
I have run into a problem of overloading a templatized operator>> by a
specialized version of it. In short (complete code below), I have
written a stream class, STR, which defines a templatized operator>>() as
a member that can deal with the built in C types (int, char, float...)

template <class tType> STR& STR::eek:perator>>(tType & t);

I then attempted to add an overloaded version of this to support my own
class, Array3d (a template class), and wrote this as a friend of Array3d as

template <class tType>
STR & operator >> ( STR & outf, Array3d<tType> & array ){}

It all compiles, but when I run the program, the lines;

str << array // str is an STR, array is an Array3d<int>

str >> array; // ...
it will call STR::eek:perator>> <Array3d<int> >, rather than (what I
belived to be) the specialized operator>>(STR &, Array3d<int> &).

Not on my system it won't.
If I instead remove the STR::eek:perator>>() and replace it by a friend
function (commented out in the code below) the function call works as i
expect it to.

Can you please enlighten me as to where I have gone wrong?
[...]

For one, all over your code you mixed operator << and operator >>,
in comments and in user-visible output.

As to which version gets used, I took your code and put it in the same
file, fixed it a bit (not functionality, just visually), and here it is:
----------------------------------------------------------------------
#include <iostream>

struct STR
{
template <class tType> STR& operator >> ( tType & );
};

template <class tType>
STR& STR::eek:perator >>( tType & obj)
{
std::cout << "MEMBER ***** STR::eek:perator >> (const tType obj)\n";
return *this;
}

template <class tType> class Array3d;
template <class tType> STR & operator >> ( STR &, Array3d<tType> & );

template <class tType> class Array3d
{
friend STR & operator >> <>( STR & of, Array3d<tType> & a );
};

template <class tType>
STR & operator >> ( STR & outf, Array3d<tType> & array )
{
std::cout << "STAND-ALONE **** STR & operator >> (STR & inf,
Array3d<tType> & array )\n";
return outf;
}

int main()
{
STR in;

Array3d<int> array;
std::cout << "Operator >> for Array3d\n";
in >> array;

std::cout << "Operator >> for int\n";
int i(3);
in >> i;

return 0;
}
 
M

Maxim Yegorushkin

Victor Bazarov wrote:

[]
----------------------------------------------------------------------
The output of it is
----------------------------------------------------------------------
Operator >> for Array3d
STAND-ALONE **** STR & operator >> (STR & inf, Array3d<tType> & array )
Operator >> for int
MEMBER ***** STR::eek:perator >> (const tType obj)

gcc 4.0.1 reports:

exp.cpp: In function 'int main()':
exp.cpp:51: error: ambiguous overload for 'operator>>' in 'in >> array'
exp.cpp:13: note: candidates are: STR& STR::eek:perator>>(tType&) [with
tType = Array3d<int>]
exp.cpp:35: note: STR& operator>>(STR&,
Array3d<tType>&) [with tType =

Here are the details:

[max@localhost exp]$ g++ -v -Wall -ggdb exp.cpp -o exp
g++ -v -Wall -ggdb exp.cpp -o exp
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--host=i386-redhat-linux
Thread model: posix
gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
/usr/libexec/gcc/i386-redhat-linux/4.0.1/cc1plus -quiet -v
-D_GNU_SOURCE exp.cpp -quiet -dumpbase exp.cpp -auxbase exp -ggdb -Wall
-version -o /tmp/ccDs1nxR.s
ignoring nonexistent directory
"/usr/lib/gcc/i386-redhat-linux/4.0.1/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/i386-redhat-linux/4.0.1/../../../../include/c++/4.0.1

/usr/lib/gcc/i386-redhat-linux/4.0.1/../../../../include/c++/4.0.1/i386-redhat-linux

/usr/lib/gcc/i386-redhat-linux/4.0.1/../../../../include/c++/4.0.1/backward
/usr/local/include
/usr/lib/gcc/i386-redhat-linux/4.0.1/include
/usr/include
End of search list.
GNU C++ version 4.0.1 20050727 (Red Hat 4.0.1-5) (i386-redhat-linux)
compiled by GNU C version 4.0.1 20050727 (Red Hat 4.0.1-5).
GGC heuristics: --param ggc-min-expand=64 --param
ggc-min-heapsize=64417
exp.cpp: In function 'int main()':
exp.cpp:51: error: ambiguous overload for 'operator>>' in 'in >> array'
exp.cpp:13: note: candidates are: STR& STR::eek:perator>>(tType&) [with
tType = Array3d<int>]
exp.cpp:35: note: STR& operator>>(STR&,
Array3d<tType>&) [with tType = int]
 
H

hall

Victor said:
For one, all over your code you mixed operator << and operator >>,
in comments and in user-visible output.

Sorry about that, I've been rewriting it som many times that comments
and output strings got mixed up...
So, I don't see a problem here...

V

I still do. Compiling it using Borland C++ builder 6 (my compiler of
choise) I get:

Operator >> for Array3d
MEMBER ***** STR::eek:perator >> (const tType obj)
Operator >> for int
MEMBER ***** STR::eek:perator >> (const tType obj)

Whereas Visual Studio.net gives the same result as you reported. I also
saw that Maxim in another answer reported that gcc 4.0.1 thought of it
as ambiguous. So which compiler gets it right, and how should this code
be written?

regards
hall
 
V

Victor Bazarov

hall said:
I still do. Compiling it using Borland C++ builder 6 (my compiler of
choise) I get:

Operator >> for Array3d
MEMBER ***** STR::eek:perator >> (const tType obj)
Operator >> for int
MEMBER ***** STR::eek:perator >> (const tType obj)

Whereas Visual Studio.net gives the same result as you reported. I also
saw that Maxim in another answer reported that gcc 4.0.1 thought of it
as ambiguous. So which compiler gets it right, and how should this code
be written?

I checked with Comeau online, after making the member operator in STR
private. It only complained about the input of an 'int', which makes me
think that Visual C++ gets it right and BC++ and G++ are both faulty.

Come to think of it, the non-member template function is actually more
specialised, so overload resolution should pick it over the less
specialised member template operator>>. That's what I think, anyway.

I suggest you contact Borland newsgroup and/or GNU C++ folk and see what
they think. Feel free to quote me.

V
 

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,777
Messages
2,569,604
Members
45,233
Latest member
AlyssaCrai

Latest Threads

Top