一个关于using namespace的问题

npuhuxl 2011-02-21 10:16:39

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>

namespace Space
{
class Class
{
public:
int value;
};
}

namespace Test
{
std::ostream& operator<<(std::ostream& os, const Space::Class& a)
{
return os<<a.value;
}
}

int main()
{

std::vector<Space::Class> v(5);
for(size_t i = 0; i < v.size(); ++ i)
v[i].value = i;

using namespace Test;
std::cout<<v[0]<<"\n"; // 没有问题

std::copy(v.begin(), v.end(),
std::ostream_iterator<Space::Class>(std::cout, "\n")); // 编译错误,找不到Test::operator<<
return 0;
}


编译器:VS2005

希望高人能解释下编译错误的原因!
...全文
245 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jinhao 2011-02-22
  • 打赏
  • 举报
回复
明显不符合标准.
std::copy的内部是*out_iterator = *in_iterator进行拷贝操作
ostream_iterator的=里用operator<<实现的,问题就出在这里
相当于operator<<(std::ostream, Space::Class)
但是你把operator<<定义namespace Test中,而没定义在namespace std或者namespace Space中.

注意,即使你把operator<<定义在全局中.在实例化std::copy模板的时候,仍然不会考虑你的定义.调用点在namespace std中,会忽略掉你在全局中的定义(被namespace std中的定义隐藏).例如下面


namespace NS
{
class T{};

void foo(int){}
}

void foo(NS::T)
{}

namespace NS
{
void test()
{
T t;
foo(t); //调用失败.NS::foo隐藏了::foo
}
}
npuhuxl 2011-02-22
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 qq120848369 的回复:]

引用 14 楼 npuhuxl 的回复:
引用 1 楼 taodm 的回复:

不要这么用namespace,没几个编译器能正确(按你的(可能错误的)理解)处理。
编程不是瞎折腾,不要搞挑战编译器的代码。



因为std::cout<<v[0]<<"\n";是可以通过编译的。
所以我想弄明白为什么std::copy不能通过编译,是编译器本身的局限还是根本这段代码不符合C++标……
[/Quote]

我明白了是什么原因了,的确是我想错了:std::ostream_iterator不能找到Test::operator<<

谢谢各位了!
jxwht005 2011-02-22
  • 打赏
  • 举报
回复
编译器的问题吧
qq120848369 2011-02-21
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 npuhuxl 的回复:]
引用 1 楼 taodm 的回复:

不要这么用namespace,没几个编译器能正确(按你的(可能错误的)理解)处理。
编程不是瞎折腾,不要搞挑战编译器的代码。



因为std::cout<<v[0]<<"\n";是可以通过编译的。
所以我想弄明白为什么std::copy不能通过编译,是编译器本身的局限还是根本这段代码不符合C++标准(2003)?
[/Quote]

因为ostream_iterator的operator =里会调用cout<<Class Obj<<endl;

但是在operator =那里是见不到你定义的重载的,所以楼上各种办法.

npuhuxl 2011-02-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 taodm 的回复:]

不要这么用namespace,没几个编译器能正确(按你的(可能错误的)理解)处理。
编程不是瞎折腾,不要搞挑战编译器的代码。
[/Quote]


因为std::cout<<v[0]<<"\n";是可以通过编译的。
所以我想弄明白为什么std::copy不能通过编译,是编译器本身的局限还是根本这段代码不符合C++标准(2003)?
qq120848369 2011-02-21
  • 打赏
  • 举报
回复
必须这样复杂,否则运行不起来.
JuanA1 2011-02-21
  • 打赏
  • 举报
回复
这简单的代码为什么要复杂化呢?
qq120848369 2011-02-21
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 jinhao 的回复:]
引用 6 楼 taodm 的回复:

呃,扩展std是违背标准规定的。


那就koenig 查找

C/C++ code

namespace Space
{
class Class
{
public:
int value;
};

std::ostream& operator<<(std::ost……
[/Quote]

学习了,

查找顺序:
1:类域(函数作为某个类的成员函数(静态或非静态))
2:名字空间域
3:全局域

Jinhao 2011-02-21
  • 打赏
  • 举报
回复
其实扩展std是比较常见的做法,要特化其中某个函数或类.连神圣的教条都允许你这么干,如果不允许的话,那真没得干了
qq120848369 2011-02-21
  • 打赏
  • 举报
回复
其实这个声明放在ostream类的头文件里更好.
Jinhao 2011-02-21
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 taodm 的回复:]

呃,扩展std是违背标准规定的。
[/Quote]

那就koenig 查找

namespace Space
{
class Class
{
public:
int value;
};

std::ostream& operator<<(std::ostream& os, const Space::Class& a)
{
return os<<a.value;
}
}



qq120848369 2011-02-21
  • 打赏
  • 举报
回复
1,少了头文件<iterator>
2,永远都不可能实现这个代码,除非你修改iterator的实现文件,在ostream_iterator的operator =
函数之前做std::ostream& operator<<(std::ostream& os, const Space::Class& a)的声明,
否则这个代码永远运行不起来.


按道理就是这样的.

taodm 2011-02-21
  • 打赏
  • 举报
回复
呃,扩展std是违背标准规定的。
昵称很不好取 2011-02-21
  • 打赏
  • 举报
回复
简单问题用复杂方案,适得其反啊
老邓 2011-02-21
  • 打赏
  • 举报
回复
namespace std
{
std::ostream& operator<<(std::ostream& os, const Space::Class& a)
{
return os<<a.value;
}
}

测试通过。
Jinhao 2011-02-21
  • 打赏
  • 举报
回复
namespace Test

改成 namespace std
才靠谱

重载是放在定义的域中.

healer_kx 2011-02-21
  • 打赏
  • 举报
回复
是啊,不用使用第二个namespace。
taodm 2011-02-21
  • 打赏
  • 举报
回复
不要这么用namespace,没几个编译器能正确(按你的(可能错误的)理解)处理。
编程不是瞎折腾,不要搞挑战编译器的代码。

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧