NULL 隐式指针转换导致不明确的重载
NULL implicit pointer conversion causing ambiguous overload
有问题的 C++03 代码:
#include <cstddef>
struct Foo {
explicit Foo(const char *){}
Foo &operator=(const char *) {return *this;}
Foo &operator=(char) {return *this;}
};
int main() {
Foo s("foobar");
s = NULL;
}
错误:
In file included from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/cstddef:50,
from <source>:1: <source>: In function 'int main()': <source>:9:9: error: ambiguous overload for 'operator=' (operand types are 'Foo' and 'long int')
9 | s = NULL;
| ^~~~ <source>:4:10: note: candidate: 'Foo& Foo::operator=(const char*)'
4 | Foo &operator=(const char *) {return *this;}
| ^~~~~~~~ <source>:5:10: note: candidate: 'Foo& Foo::operator=(char)'
5 | Foo &operator=(char) {return *this;}
| ^~~~~~~~
如果我没理解错的话,问题的根源在于C++03中的NULL
既可以作为整数又可以作为指针。我也知道C++11及以后提供nullptr
来解决这个问题。升级到 C++11 对我来说不是一个选择。
问题:这个问题在实践中是如何解决的,如何保持提供重载的能力?
一种方法是告诉用户不要使用 NULL
。有程序化的解决方案吗?
实现它的一种方法是使用 char
的代理结构,这将使 operator=(const char*)
更受欢迎。像这样:
#include <cstddef>
struct MyChar
{
MyChar(char c) : c(c){}
operator char() {return c;}
char c;
};
struct Foo {
explicit Foo(const char *){}
Foo &operator=(const char *) {return *this;}
Foo &operator=(MyChar) {return *this;}
};
int main() {
Foo s("foobar");
s = NULL;
s = 'x';
s = "foo";
}
有问题的 C++03 代码:
#include <cstddef>
struct Foo {
explicit Foo(const char *){}
Foo &operator=(const char *) {return *this;}
Foo &operator=(char) {return *this;}
};
int main() {
Foo s("foobar");
s = NULL;
}
错误:
In file included from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/cstddef:50,
from <source>:1: <source>: In function 'int main()': <source>:9:9: error: ambiguous overload for 'operator=' (operand types are 'Foo' and 'long int')
9 | s = NULL;
| ^~~~ <source>:4:10: note: candidate: 'Foo& Foo::operator=(const char*)'
4 | Foo &operator=(const char *) {return *this;}
| ^~~~~~~~ <source>:5:10: note: candidate: 'Foo& Foo::operator=(char)'
5 | Foo &operator=(char) {return *this;}
| ^~~~~~~~
如果我没理解错的话,问题的根源在于C++03中的NULL
既可以作为整数又可以作为指针。我也知道C++11及以后提供nullptr
来解决这个问题。升级到 C++11 对我来说不是一个选择。
问题:这个问题在实践中是如何解决的,如何保持提供重载的能力?
一种方法是告诉用户不要使用 NULL
。有程序化的解决方案吗?
实现它的一种方法是使用 char
的代理结构,这将使 operator=(const char*)
更受欢迎。像这样:
#include <cstddef>
struct MyChar
{
MyChar(char c) : c(c){}
operator char() {return c;}
char c;
};
struct Foo {
explicit Foo(const char *){}
Foo &operator=(const char *) {return *this;}
Foo &operator=(MyChar) {return *this;}
};
int main() {
Foo s("foobar");
s = NULL;
s = 'x';
s = "foo";
}