c++输出流不适用于模板和 namespace

标签 c++ templates visual-c++ namespaces ostream

我有以下代码:

#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 的函数类,一切正常。

这是 MSVC 中的错误吗?如何在不删除 namespace 或函数的情况下编译它?

最佳答案

这是您代码中的错误。函数的重载集是分多个阶段构建的:

  1. 从当前作用域向外找到一个匹配的函数名。当在命名空间中找到名称时,将此命名空间中定义的所有重载添加到重载集中并停止此过程。
  2. 将参数相关查找 (ADL) 找到的所有重载添加到重载集中。
  3. 确定重载集是否包含唯一匹配和最佳重载。如果是,则使用它,否则失败。

你的问题是你的 operator<<(std::ostream&, baz::Bar&)在全局命名空间中定义,而不是在 Bar 所在的命名空间中定义已定义(在本例中为 baz )。将重载放入命名空间 baz在使用名称取决于模板参数的模板中的运算符时无论如何都需要:在这种情况下,第一阶段被省略,并且仅检测通过参数相关查找找到的名称。

顺便说一句,在固定输出运算符的位置时,您可能需要考虑将参数作为 baz::Bar const& 传递因为输出运算符通常不会修改格式化实体。

关于c++输出流不适用于模板和 namespace ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34198039/

相关文章:

c++ - 我无法找到这些代码段的 Big O 表示法

c++ - 模板中的函数类型无法编译

c++ - 为什么我可以在 MSVC 和 icc 中为 glm::vec 创建用户定义的结构化绑定(bind),但不能在 Clang 和 GCC 中创建?

c++ - Boost 单元测试在 Visual Studio 2012 中抛出异常

c++ - 你能用 UTF8Encode 将 System::String^ 编码为 Byte* 吗?

c++ - 从 C++ 中的系统命令检索 ping 时间 (ping x.x.x.x -n)

c++ - OpenGL找不到一些统一变量

c++ - 非类型模板参数

javascript - 带有 grunt-dr-svg-sprites 的 HBS 模板

c++ - 如何在可变参数模板中获取嵌套参数包?