为什么std :: nullptr_t在C++中不能与std :: cout一起使用?

6 c++ ambiguous nullptr c++14

我了解到std::nullptr_t这是空指针文字的类型,nullptr.

然后我做了一个小程序:

#include <iostream>

int main() 
{
    std::nullptr_t n1; 
    std::cout<<n1<<endl;
    return 0;
} 
Run Code Online (Sandbox Code Playgroud)

这里nullptr_t是数据类型并且n1是可变的,我正在尝试打印变量的值.但是,编译器给出了一个错误:

prog.cpp: In function 'int main()':
prog.cpp:6:11: error: ambiguous overload for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'std::nullptr_t')
  std::cout<<n1<<endl;
Run Code Online (Sandbox Code Playgroud)

为什么不std::nullptr_t 一起工作std::cout在C++?我错在哪里?

cdh*_*wie 9

operator<<对于多个不同类型的指针,输出流有重载,但不是std::nullptr_t 1.这意味着编译器无法确定要调用哪个重载,因为任何接受指针的重载都同样好.(例如,它接受char const *C风格的字符串,并且还会void const *输出原始指针值.)

修复此问题的一个选项是定义自己的重载,强制使用void const *重载:

std::ostream & operator<<(std::ostream &s, std::nullptr_t) {
    return s << static_cast<void *>(nullptr);
}
Run Code Online (Sandbox Code Playgroud)

或者让它做其他事情:

std::ostream & operator<<(std::ostream &s, std::nullptr_t) {
    return s << "nullptr";
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 1正如评论中所指出的,std::nullptr_t在C++ 17中有一个过载接受,所以如果你使用一致的C++ 17实现,这将不再是一个问题.
  • endl需要std::资格 - 但'\n'无论如何你应该在这里使用.(std::endl当你需要刷新流时,这只是一个好主意.)

  • 请注意,此问题已在C++ 17中得到解决:http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt但是,我尝试过的编译器似乎都没有支持它. (3认同)
  • 在类型命名空间之外重载操作符是不好的,而在std中是非法的. (2认同)
  • @fureeeish在定义类型(不是类型转换)的命名空间之外重载一个重要性和区别的运算符,由于ADL失败,在定义重载时不太理想(可以说是坏的)的想法在命名空间内std是不明智的,因为它会使你的程序形成为建议的动作.因此,我们贬低这句话,如果一个人这样做,那就是该死的,所以不要这样做.如果从外部std键入一个模板参数,那么你的困境将在没有麻烦的潮流中被洗掉.(就像我给出的字符限制一样精心制作) (2认同)