Cross-namespace name lookup

M

Marcin Kalicinski

Is the code below ill formed (because operator >> is defined in different
namespace than class B)?

It fails with VS 2005 Beta. I don't know if I should redesign my code or if
I should find a better compiler?

namespace N1
{
class A { };
std::istream &operator >>(std::istream &, A &);
}

namespace N2
{
class B: public A { };
}

void f()
{
A a;
B b;
cin >> a; // OK
cin >> b; // Error: cannot find a matching operator >> for class B
}
 
M

mrstephengross

Interesting... I guess the search rules don't include namespaces of
base classes... Could you cast the B instance as an A ("cin >> (A)b") ?
Or could you put the operator>>() definition in the std namespace?

--Steve
 
D

Dan Cernat

Marcin said:
Is the code below ill formed (because operator >> is defined in different
namespace than class B)?

It fails with VS 2005 Beta. I don't know if I should redesign my code or if
I should find a better compiler?

namespace N1
{
class A { };
std::istream &operator >>(std::istream &, A &);
}

namespace N2
{
class B: public A { };
}

void f()
{
A a;
B b;
cin >> a; // OK
cin >> b; // Error: cannot find a matching operator >> for class B
}

This is not the real code, is it? I copy-pasted this code in VS 2003
and I cannot compile the declaration of B since its base class is in a
different namespace. That is why I doubt this is real code.

The code below compiles:
#include <iostream>

namespace N1
{
class A { };
std::istream &operator >>(std::istream & x, A &){return x;}
}


namespace N2
{
class B: public N1::A { };
}


int main()
{
N1::A a;
N2::B b;
std::cin >> a; // OK
std::cin >> b; // OK

return 0;
}

/dan
 
M

Marcin Kalicinski

Interesting... I guess the search rules don't include namespaces of
base classes... Could you cast the B instance as an A ("cin >> (A)b") ?
Or could you put the operator>>() definition in the std namespace?

Possibly both of these solve the problem. Unforunately, I probably cannot
use any of them! First, function f in my code is actually a template:

template<class T> void f(T &t) { cin >> t; }

So I cannot make the cast :-(

Second, putting anything in std namespace is undefined behavior, as far as I
remember C++ standard.

The original code again:

namespace N1
{
class A { };
std::istream &operator >>(std::istream &, A &);
}

namespace N2
{
class B: public A { };
}

void f()
{
A a;
B b;
cin >> a; // OK
cin >> b; // Error: cannot find a matching operator >> for class B
}
 
M

mrstephengross

Possibly both of these solve the problem. Unforunately, I probably cannot
use any of them! First, function f in my code is actually a template:
template<class T> void f(T &t) { cin >> t; }
So I cannot make the cast :-(

Yes you can! :) Here's how:

#include "boost/mpl/is_same.hpp"

struct streamAsNormal { template<typename T> static void go(const
std::istream & i, T & t) { i >> t; } };
struct streamAsBase { template<typename T> static void go(const
std::istream & i, T & t) { i >> (A)t; } };

template<class T> void f(T &t)
{
boost::if<boost::is_same<T, B>::type, streamAsBase,
streamAsNormal>::type::go(cin, t);
}

--Steve
 
M

Marcin Kalicinski

Hi,

Yes, you're right. The code is not real, I wrote it only to illustrate the
real problem found in my program. Of course I forgot the namespace qualifier
in class B definition.

I'm sorry to say that but it really compiles, as you said. So I started
digging deeper in my code and found out that the real problem is different
(see bottom for new code). I'm saying sorry to all the people who answered
my initial post...

// The code illustrating the problem:

namespace N1
{
class A { };
}

namespace N2
{
class B: public N1::A { };
}

namespace N3
{
std::istream &operator >>(std::istream & x, N1::A &){return x;}
}

int main()
{
N1::A a;
N2::B b;
std::cin >> a; // Error
std::cin >> b; // Error
return 0;
}

I would like to move operator >> to namespace N1 very much, but I cannot
because namespace N1 is actually namespace std, and class N1::A is
std::vector. Maybe the whole idea of defining stream operations for std
containers is bad?
 
D

Dan Cernat

See my comment before main()


Marcin said:
Hi,

Yes, you're right. The code is not real, I wrote it only to illustrate the
real problem found in my program. Of course I forgot the namespace qualifier
in class B definition.

I'm sorry to say that but it really compiles, as you said. So I started
digging deeper in my code and found out that the real problem is different
(see bottom for new code). I'm saying sorry to all the people who answered
my initial post...

// The code illustrating the problem:

namespace N1
{
class A { };
}

namespace N2
{
class B: public N1::A { };
}

namespace N3
{
std::istream &operator >>(std::istream & x, N1::A &){return x;}
}

// let the compiler know where else to look up the names
using namespace N3;

int main()
{
N1::A a;
N2::B b;
std::cin >> a; // Error
std::cin >> b; // Error
return 0;
}

I would like to move operator >> to namespace N1 very much, but I cannot
because namespace N1 is actually namespace std, and class N1::A is
std::vector. Maybe the whole idea of defining stream operations for std
containers is bad?

it should compile now.

/dan
 
B

Ben Pope

Marcin said:
Hi,

Yes, you're right. The code is not real, I wrote it only to illustrate the
real problem found in my program. Of course I forgot the namespace qualifier
in class B definition.

I'm sorry to say that but it really compiles, as you said. So I started
digging deeper in my code and found out that the real problem is different
(see bottom for new code). I'm saying sorry to all the people who answered
my initial post...

// The code illustrating the problem:

namespace N1
{
class A { };
}

namespace N2
{
class B: public N1::A { };
}

namespace N3
{
std::istream &operator >>(std::istream & x, N1::A &){return x;}
}

int main()
{
N1::A a;
N2::B b;
std::cin >> a; // Error
std::cin >> b; // Error
return 0;
}

I would like to move operator >> to namespace N1 very much, but I cannot
because namespace N1 is actually namespace std, and class N1::A is
std::vector. Maybe the whole idea of defining stream operations for std
containers is bad?

std::vector doesn't have a virtual destructor, are you sure you want to inherit from it?

Perhaps you should compose B from a std::vector, might solve your problems, too.

Ben
 
W

Wisdo Tang

Dan Cernat said:
See my comment before main()




// let the compiler know where else to look up the names
using namespace N3;

The idea is no bad, but the namespace look up mechanism can't auto find
operators.
Giving thee using namespace is OK when using it.
You indeed expect the operators can be found automatically?

it should compile now.

/dan

No, it doesn't pass still.
I think the compile can't find the operator>> in the statement
std::cin,isn't it.


Wisdo Tang
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top