为什么'std::ostream&operator<<'覆盖必须在C++'global'范围内声明?



描述

我将用std::ostream替代<< operator,以简化代码中的对象显示。我使用不同的名称空间来定义要显示的对象类型。

这导致我出现编译错误。我找到了解决办法。似乎覆盖必须在全局范围内声明,但我真的不明白为什么。有人能解释一下错误的原因吗?

错误

main.cpp:22:38: error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream’ and ‘std::vector’)
std::cout <<"printVector = " << data << std::endl;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~

示例代码(不编译(

下面是一个伪示例来显示错误。

#include <iostream>
#include <vector>
inline std::ostream&
operator<<(std::ostream& strm, std::vector<uint8_t>& buffer)
{
return strm << "display std::vector<uint8_t>";
}

namespace aNamespace {
enum TestEnum { a, b, c };

inline std::ostream&
operator<<(std::ostream& strm, TestEnum& value)
{
return strm << "display TestEnum";
}

static void printVector () 
{
std::vector<uint8_t> data {1, 12, 56, 241, 128};
std::cout <<"printVector = " << data << std::endl;
}
}

int main()
{
aNamespace::printVector();
return 0;
}

环境

C++11;GCC;Linux

示例代码修复程序(已编辑(

这是一个修复版本的代码,适用于那些被质疑的人。

#include <iostream>
#include <vector>
inline std::ostream&
operator<<(std::ostream& strm, std::vector<uint8_t>& buffer)
{
return strm << "display std::vector<uint8_t>";
}
namespace aNamespace {
using ::operator<<;
enum class TestEnum { a, b, c };

inline std::ostream&
operator<<(std::ostream& strm, TestEnum value)
{
return strm << "display TestEnum";
}
static void printVector () 
{
std::vector<uint8_t> data {1, 12, 56, 241, 128};
std::cout <<"printVector = " << data << std::endl;
}
}
int main()
{
aNamespace::printVector();
return 0;
}

ADL再次罢工

为了解决运算符重载,C++使用参数相关查找。简而言之,它将搜索任一参数的命名空间(在本例中为命名空间std(和运算符调用的命名空间(aNamespace(,如果未找到运算符重载,则向上搜索层次结构

命名空间std不包含任何匹配重载,但它包含其他不匹配重载,因此不会搜索父命名空间。

现在,如果名称空间aNamespace不包含operator <<的任何重载,则搜索父名称空间(全局(并找到正确的重载,就像在您的";示例代码修复";例如
但是,如果它包含operator <<的任何重载,即使是不匹配的重载,查找也不会考虑父命名空间,并且找不到正确的重载。

这就是为什么一些C++大师反对广泛使用名称空间的原因之一,或者至少将其限制在每个项目的一个名称空间内(例如参见Titus Winters的这篇文章(。


一个可能的修复方法如您所列,但当编译器使用aNamespace::TestEnum查找重载时,它本身可能会出现问题。首选在封装其中一个参数的命名空间中具有运算符重载。

更好的解决方案是从全局范围显式地将运算符添加到您的命名空间范围或函数范围:

using ::operator<<;

相关内容

最新更新