c ++输出流不适用于模板和名称空间
c++ Output stream not working with templates and namespaces
我有以下代码:
#include <fstream>
// Removing this namespace (keeping the content) makes it work
namespace baz {
class Bar {
};
}
std::ostream & operator<<(std::ostream & stream, baz::Bar & value) {
return stream;
}
// Removing this namespace (keeping the content) makes it work
namespace goo {
template <class Type>
struct Point {
};
// Removing this function makes it work
template <class Type>
std::ostream& operator<< (std::ostream& stream, const Point<Type> &point);
void foo() {
baz::Bar test;
std::ofstream stream;
stream << test;
}
}
它无法在 MSVC 上编译并失败并显示以下错误消息:
error C2679: binary '<<' : no operator found which takes a right-hand
operand of type 'baz::Bar' (or there is no acceptable conversion)
但是,如果我删除两个命名空间中的任何一个(保留所有内容)或删除 Point
class 的模板化 <<
函数,一切正常。
这是 MSVC 中的错误吗?如何在不删除命名空间或函数的情况下编译它?
这是您的代码中的错误。函数的重载集是分多个阶段构建的:
- 从当前范围向外找到一个匹配的函数名。当在命名空间中找到名称时,将此命名空间中定义的所有重载添加到重载集中并停止此过程。
- 将参数相关查找 (ADL) 找到的所有重载添加到重载集中。
- 确定重载集是否包含唯一匹配和最佳重载。如果是这样,使用它,否则失败。
您的问题是您的 operator<<(std::ostream&, baz::Bar&)
是在全局命名空间中定义的,而不是在定义 Bar
的命名空间中(在本例中为 baz
)。当使用名称取决于模板参数的模板中的运算符时,无论如何都需要将重载放入命名空间 baz
中:在这种情况下,第一阶段被省略,并且仅检测到通过参数相关查找找到的名称。
顺便说一句,在固定输出运算符的位置时,您可能需要考虑将参数作为 baz::Bar const&
传递,因为输出运算符通常不会修改格式化实体。
我有以下代码:
#include <fstream>
// Removing this namespace (keeping the content) makes it work
namespace baz {
class Bar {
};
}
std::ostream & operator<<(std::ostream & stream, baz::Bar & value) {
return stream;
}
// Removing this namespace (keeping the content) makes it work
namespace goo {
template <class Type>
struct Point {
};
// Removing this function makes it work
template <class Type>
std::ostream& operator<< (std::ostream& stream, const Point<Type> &point);
void foo() {
baz::Bar test;
std::ofstream stream;
stream << test;
}
}
它无法在 MSVC 上编译并失败并显示以下错误消息:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'baz::Bar' (or there is no acceptable conversion)
但是,如果我删除两个命名空间中的任何一个(保留所有内容)或删除 Point
class 的模板化 <<
函数,一切正常。
这是 MSVC 中的错误吗?如何在不删除命名空间或函数的情况下编译它?
这是您的代码中的错误。函数的重载集是分多个阶段构建的:
- 从当前范围向外找到一个匹配的函数名。当在命名空间中找到名称时,将此命名空间中定义的所有重载添加到重载集中并停止此过程。
- 将参数相关查找 (ADL) 找到的所有重载添加到重载集中。
- 确定重载集是否包含唯一匹配和最佳重载。如果是这样,使用它,否则失败。
您的问题是您的 operator<<(std::ostream&, baz::Bar&)
是在全局命名空间中定义的,而不是在定义 Bar
的命名空间中(在本例中为 baz
)。当使用名称取决于模板参数的模板中的运算符时,无论如何都需要将重载放入命名空间 baz
中:在这种情况下,第一阶段被省略,并且仅检测到通过参数相关查找找到的名称。
顺便说一句,在固定输出运算符的位置时,您可能需要考虑将参数作为 baz::Bar const&
传递,因为输出运算符通常不会修改格式化实体。