简体   繁体   English

c ++输出流不使用模板和命名空间

[英]c++ Output stream not working with templates and namespaces

I have the following code: 我有以下代码:

#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;
}

}

It does not compile on MSVC and fails with the following error message: 它不在MSVC上编译并失败,并显示以下错误消息:

error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'baz::Bar' (or there is no acceptable conversion) 错误C2679:二进制'<<':找不到哪个运算符采用'baz :: Bar'类型的右手操作数(或者没有可接受的转换)

However, if I remove any of the two namespaces (keeping all the contents) or remove the templated << function for the Point class, everything works fine. 但是,如果我删除任何两个名称空间(保留所有内容)或删除Point类的模板化<<函数,一切正常。

Is this a bug in MSVC? 这是MSVC中的错误吗? How can I make it compile without removing the namespaces or the function? 如何在不删除命名空间或函数的情况下进行编译?

This is a bug in your code. 这是您的代码中的错误。 The overload set for functions is build in multiple stages: 函数的重载集是在多个阶段构建的:

  1. From the current scope outwards find a matching function name. 从当前范围向外找到匹配的函数名称。 When a name is found in a namespace add all overloads defined in this namespace to the overload set and stop this process. 在命名空间中找到名称时,将此命名空间中定义的所有重载添加到重载集并停止此过程。
  2. Add all overloads found by argument dependent look-up (ADL) to the overload set. 将依赖于参数的查找(ADL)找到的所有重载添加到重载集。
  3. Determine if the overload set contains a unique matching and best overload. 确定过载集是否包含唯一匹配和最佳过载。 If so, use that otherwise fail. 如果是这样,请使用否则失败。

Your problem is that your operator<<(std::ostream&, baz::Bar&) is defined in the global namespace rather than in the namespace where Bar is defined (in this case baz ). 您的问题是您的operator<<(std::ostream&, baz::Bar&)是在全局命名空间中定义的,而不是在定义了Bar的命名空间中定义的(在本例中为baz )。 Putting the overload into namespace baz is needed anyway when using the operator from a template with a name depending on a template argument: in that case the first stage is omitted and only names found by argument dependent look-up are detected. 无论如何,当从具有名称取决于模板参数的模板使用运算符时,需要将重载置于名称空间baz中:在这种情况下,第一阶段被省略,并且仅检测由参数依赖查找找到的名称。

BTW, while fixing the location of the output operator you might want to consider passing the argument as baz::Bar const& as output operators normally don't modify the formatted entity. 顺便说一句,在修复输出操作符的位置时,您可能需要考虑将参数作为baz::Bar const&传递,因为输出操作符通常不会修改格式化的实体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM