operators & namespaces

  • Thread starter =?ISO-8859-1?Q?Alexander_B=FCrger?=
  • Start date
?

=?ISO-8859-1?Q?Alexander_B=FCrger?=

Hi,

I have a little problem with classes in a namespace and an operator
defined for these classes outside that namespace. Example:

// -------------------------------------------------------------------
#include <iostream>
#include <vector>

namespace N {
struct A { int a; };
A& operator<<(A& a, int i)
{ std::cout << "i=" << i << '\n'; return a; }
A& operator<<(A& a, float f)
{ std::cout << "f=" << f << '\n'; return a; }
}

template<typename T>
void WriteVector(N::A& a, std::vector<T> const& v)
{
typename std::vector<T>::const_iterator it;
for( it=v.begin(); it!=v.end(); ++it )
a << *it;
}

template<typename T>
inline N::A& operator<<(N::A& a, std::vector<T> const& v)
{ WriteVector( a, v ); return a; }

namespace N {
void go() {
std::vector<int> v;
for( int i=0; i<5; ++i )
v.push_back( 1<<i );
A a;
WriteVector( a, v );
a << v;
}
}
int main()
{
N::go();
}
// -------------------------------------------------------------------

The compiler (g++) gives me the following error message:

######################################################################
In function 'void N::go()':
error: no match for 'operator<<' in 'a << v'
note: candidates are: N::A& N::eek:perator<<(N::A&, int)
note: N::A& N::eek:perator<<(N::A&, float)
######################################################################

So while the operator<< template is not found, the WriteVector version
is. How can I help the compiler to find the operator<< version?

Thanks for your advice,

Alexander

PS: For email reply, please remove the six appropriate letters from the
given address.
 
I

Ian Collins

Alexander said:
Hi,

I have a little problem with classes in a namespace and an operator
defined for these classes outside that namespace. Example:

// -------------------------------------------------------------------
#include <iostream>
#include <vector>

namespace N {
struct A { int a; };
A& operator<<(A& a, int i)
{ std::cout << "i=" << i << '\n'; return a; }
A& operator<<(A& a, float f)
{ std::cout << "f=" << f << '\n'; return a; }

You can either add a prototype in the namespace

template<typename T>
A& operator said:
}

template<typename T>
void WriteVector(N::A& a, std::vector<T> const& v)
{
typename std::vector<T>::const_iterator it;
for( it=v.begin(); it!=v.end(); ++it )
a << *it;
}
Or put the operator in the namespace.

namespace N {
template<typename T>
inline N::A& operator<<(N::A& a, std::vector<T> const& v)
{ WriteVector( a, v ); return a; }
}
 
B

Bo Yang

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ian Collins :
You can either add a prototype in the namespace

template<typename T>

Or put the operator in the namespace.

namespace N {

}

It is ok when using either of you method .
But , why c++ can't find the symbol , does c++
only find the definition in the namespace ?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFTXDG7tZp58UCwyMRAsfQAJ459v/lbClnAGvcPH13fuvZGRpJXQCfcuA5
+EAKf56k76P3o3vN16lcm2o=
=JgNA
-----END PGP SIGNATURE-----
 
?

=?ISO-8859-1?Q?Alexander_B=FCrger?=

Hi Ian,

thank you for your answer.
You can either add a prototype in the namespace

template<typename T>
A& operator<<(A& a, std::vector<T> const& );

Unfortunately, g++ does not like this either. Either the linker
complains or, if I write ::eek:perator, the compiler complains that I try
to declare something in the wrong namespace.
Or put the operator in the namespace.

Of course.


It also works after replacing the operator<< functions in namespace N
with "named" functions. Apparently the compiler stops searching as soon
as it found any operator<< in namespace N, independent of the signature.
The following code compiles only if NO_B is defined:

// -------------------------------------------------------------
#include <iostream>
#include <vector>

namespace N {
struct A { int a; };
void Write( A&, int i) { std::cout << "i=" << i << '\n'; }
void Write( A&, float f) { std::cout << "f=" << f << '\n'; }
#ifndef NO_B
struct B { int b; };
B& operator<<(B& b, float f)
{ std::cout << "f=" << f << '\n'; return b; }
#endif
}

template<typename T>
void WriteVector(N::A& a, std::vector<T> const& v)
{
typename std::vector<T>::const_iterator it;
for( it=v.begin(); it!=v.end(); ++it )
Write( a, *it );
}

template<typename T>
inline N::A& operator<<(N::A& a, std::vector<T> const& v)
{ WriteVector( a, v ); return a; }

namespace N {
void go() {
std::vector<int> v;
for( int i=0; i<5; ++i )
v.push_back( 1<<i );
A a;
a << v;
}
}
int main()
{
N::go();
}
// -------------------------------------------------------------

So I think I understood where the problem comes from, although I do see
no reason why the compiler does not search for a good signature in the
enclosing namespaces.

Best wishes,

Alexander
 

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,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top