当我试图通过std::copy输出元素时,我遇到了令人费解的行为。下面的代码正在编译,并且工作正常。
namespace Foo {
enum class Colors { green, red, blue };
template <typename T>
std::ostream &operator << (std::ostream &_os, const T &_t) {
_os << typename std::underlying_type<T>::type(_t);
return _os;
}
}
int main() {
Foo::Colors colors[] = {Foo::Colors::red, Foo::Colors::red, Foo::Colors::blue};
for( auto c: colors ) { std::cout << c <<std::endl; }
std::copy(colors, colors + 4, std::ostream_iterator<Foo::Colors>(std::cout, " "));
}但是,如果我将operator <<转移到Foo作用域之外,std::copy就会出现问题。
namespace Foo {
enum class Colors { green, red, blue };
}
template <typename T>
std::ostream &operator << (std::ostream &_os, const T &_t) {
_os << typename std::underlying_type<T>::type(_t);
return _os;
}
int main() {
Foo::Colors colors[] = {Foo::Colors::red, Foo::Colors::red, Foo::Colors::blue};
for( auto c: colors) { std::cout << c <<std::endl; } // works fine
// arising compiler error
std::copy(colors, colors + 4, std::ostream_iterator<Foo::Colors>(std::cout, " "));
// do not help, too
{
using namespace Foo;
std::copy(colors, colors + 4, std::ostream_iterator<Colors>(std::cout, " "));
}
}此行为的原因是什么,以及解决此问题的正确方法是什么?
发布于 2014-03-13 16:30:55
您的模板正在接受所有内容,并将导致模棱两可:
一个较小的测试用例:
#include <iostream>
// error: ambiguous overload for ‘operator<<’ in ‘std::cout << '\012'’
template <typename T>
std::ostream &operator << (std::ostream &_os, const T &_t) {
_os << typename std::underlying_type<T>::type(_t);
return _os;
}
int main() {
std::cout << '\n';
}只有一个且只有一个(!)由于ADL (参数相关查找),命名空间中的运算符<<将解析它。
发布于 2014-03-13 19:06:20
原因是std::ostream_iterator<Foo::Colors>搜索operator<<,而它本身在名称空间std中。通常的非限定查找将只在包含具有该名称的函数的最近封闭类或命名空间中查找函数。例如:
void meow(int);
namespace foo
{
void meow(double);
void find_kitten()
{
meow(42); // calls `foo::meow(double)`
}
}同样的事情也发生在operator<<身上。在名称空间std中存在此运算符的重载,因此,非限定名称查找停止并且不搜索全局名称空间。
但是,对于运算符,始终会发生参数相关的查找。如果您的函数模板位于某个参数类型的关联命名空间中,它将找到您的函数模板。这是第一个示例中的情况,但不是第二个示例中的情况。
附注:
请编译并显示警告,您的函数模板缺少返回值:
std::ostream &operator << (std::ostream &_os, const T &_t) {
_os << typename std::underlying_type<T>::type(_t);
return _os; // <--- missing
}https://stackoverflow.com/questions/22372886
复制相似问题