为什么将"<<"运算符作为函数调用会导致"ambiguous call"编译器错误?

Why calling the "<<" operator as a function causes "ambiguous call" compiler error?

本文关键字:lt ambiguous call 编译器 错误 运算符 为什么 函数调用      更新时间:2023-10-16

为什么第一个代码片段工作正常,但第二个代码片段导致不明确的调用错误?为什么编译器无法解决第二种情况下的函数重载?

片段 1:

int main() {
int x = 1234;
std::cout << x;
}

片段 2:

int main() {
int x = 1234;
operator<<(std::cout, x);
}

编译代码段 2 时的编译器错误:

more than one instance of "operator<<" matches the argument list
std::operator <<': ambiguous call to overloaded function

因为整数没有全局(或非成员(operator<<重载函数。它是输出流的成员:

std::cout.operator<<(x);

一个好的编译器应该向你展示一个模棱两可的调用的可能替代方案,它应该告诉你这一点。

您正在尝试调用成员函数(std::cout(,就好像它是一个自由函数一样:http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt

歧义可能来自多匹配,这些匹配都涉及某种转换,其中没有一种是可取的。编译器错误可能会给你一些可怕的不可能阅读的可能匹配列表,所有这些似乎都无关紧要?

对于运算符,

请将它们称为运算符,而不是函数!有充分的理由将运算符定义为成员,并且有充分的理由将它们定义为自由函数。您不需要关心在任何特定情况下使用哪个。

如果我想创建自己的支持+的类型,我可能有很好的技术理由选择一种方法而不是另一种方法,甚至在库的未来版本中改变主意。你应该在乎我选择哪个吗?


请注意,operator<<是内置类型(即int的各种风格(的成员函数,但对于其他类型的函数,例如char const*std::string是非成员函数。

运算符是一个非静态成员函数,因此您可以使用 来自 : 如何在C++中将运算符作为函数调用

#include <iostream>
int main() {
int x = 1234;
std::cout.operator<<(x);
}

从这里:

template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
char ch );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
signed char ch );

如果重载解析无法选择比此类不可微分函数唯一更好的调用匹配项,则调用将不明确。对于x(int(,char版本和signed char版本都适合,因此会模棱两可。再举一个例子:

#include <iostream>
void foo(char a)
{
}
void foo(signed char b)
{
}
int main() {
foo(1);
}

prog.cc:在函数 'int main((' 中: prog.cc:11:10:错误:重载的"foo(int("调用不明确 福(1(;


但是这段代码可以正常工作运算符<<(std::cout, "hello"(;

因为

template< class Traits > basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& const char* s );

operator<<(std::cout, "hello");的唯一选择。再举一个例子:

const char* z = "char*";  // OK 
const signed char* x = "signed char*";  // invalid conversion from ‘const char*’ to ‘const signed char*’ 
const unsigned char y = "unsigned char*"; // invalid conversion from ‘const char*’ to ‘unsigned char’