指针和整数的重载模糊不清?

7
以下是重载函数,
void foo(const void*)
{
  printf("first");
}

void foo(unsigned int)
{
  printf("second");
}

生成了一个在这种情况下模棱两可的重载
foo((int)0);

但不在这个里面

foo((int)1);

为什么?是因为人们仍然使用NULL吗?在不进行显式转换的情况下,解决问题的最佳方法是什么?
(我使用GCC 8.3.0-C++11在Ubuntu 18.04上编译) Godbolt一致性视图 编辑
正如你们中的一些人在评论中指出的那样,(int)0实际上可以编译而没有错误(至少在GCC 8.3.0中,使用C++11 std)。我遇到的问题只是在foo(0)中,现在我明白了原因。

3
问题在于,(int)0 不应引起歧义。只有字面值 0 才构成空指针常量,而强制类型转换表达式并不构成。你使用了哪些编译器选项来构建代码? - StoryTeller - Unslander Monica
1
是的,我无法重现你的问题 https://wandbox.org/permlink/GKRgIv2CTNZ7XhR9 - 对于(int)0,按预期调用了第二个重载。 - StoryTeller - Unslander Monica
1
我可以在gcc中重现这个问题这里,但在clang中无法。 - ChrisD
2
@IlCapitano - 它应该在C++98模式下运行。这里涉及到一个缺陷http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#903,它没有被追溯地应用于C++03。 - StoryTeller - Unslander Monica
1
有趣的是,如果你从函数重载中去除 foo(unsigned int),代码将无法编译。我不确定为什么函数 foo(const void*) 在有两个候选项时调用模糊,但是使用 (int)0 调用唯一的候选者 foo(const void*) 是不正确的。 - NotAProgrammer
显示剩余7条评论
2个回答

6
在C和C++中,字面量0具有特殊含义,因为它也是一个空指针字面量。这就是NULL的工作原理。
如果您正在使用字面量调用函数,而不是foo(0),您可以使用foo(0u),因为0u已经具有unsigned int类型,所以调用整数重载时不需要转换。如果您使用整数变量调用foo,则不应该有任何冲突。(演示在此处)

如评论中所述,(int)0不应该引起任何冲突,而且在C++11模式下,GCC 8.3 没有错误,使用foo((int)0),但是在C++98模式下(以及clang),会报错。正如@StoryTeller-UnslanderMonica在评论中提到的那样,这是由一个缺陷引起的http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#903,该缺陷没有被追溯地应用于C++98。


0
在像你这样的情况下,通常可以使用SFINAE或requires()来帮助自己。这是一个想法,但也有其他解决方案:
void foo(void const*)
{
  printf("first");
}

void foo(auto a)
  requires(
    std::is_integral_v<decltype(a)> &&
    !std::is_same_v<decltype(NULL), decltype(a)>
  )
{
  printf("second");
}

演示

但是,在 C++ 中,NULL 通常不会成为问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接