我正在阅读Unexpected value using random number generator as a function in C++,评论和当前回答表明用户正在输出该功能的地址。这听起来很合理。我假设发生了函数到指针转换,因此匹配const void*
重载,但是在自己测试时,我在GCC / Clang和MSVC中获得了不同的结果。以下测试程序:
#include <iostream>
void test()
{
}
void func(bool)
{
std::cout << "bool";
}
void func(const void*)
{
std::cout << "const void*";
}
int main()
{
func(test);
}
在GCC / Clang中输出bool
( coliru
)
和const void*
( rextester
警告实时协作链接)
N3337说:
[conv.func]
函数类型
T
的左值可以转换为类型的prvalue &#34;指向T
的指针。&#34;结果是指向函数的指针。
[conv.bool]
算术,无范围枚举,指针或指针的prvalue 成员类型可以转换为
bool
类型的prvalue。零 转换value,null指针值或null成员指针值 到false
;任何其他值都将转换为true
。一个类型的prvaluestd::nullptr_t
可以转换为bool类型的prvalue;该 结果值为false
。
因此,一个不是转换为bool的空指针值的指针应该等于true
,这解释了GCC / Clang给出的警告。
然后表12 [over.ics.scs]下的转换给出了一个函数到指针的转换&#34;完全匹配&#34;排名和布尔转换&#34;转换&#34;秩。 [over.ics.rank] / 4然后说:
标准转换序列按其等级排序:精确 匹配是比促销更好的转换,这是更好的 转换比转换。两个转换序列相同 除非符合以下规则之一,否则等级无法区分:
- 不转换指针的转换,指向成员的指针, 或
std::nullptr_t
至bool
优于const void*
。{/ p>- [...]
我不是语言律师,所以我希望我引用正确的部分。
然而,即使bool
重载不存在,MSVC也会调用bool
重载,反之亦然:即使const void*
,GCC / Clang也会调用{{1}}重载超载是不存在的。所以我不清楚这里的转换。有人可以为我清楚这一点吗?
答案 0 :(得分:3)
似乎是MSVC中的错误(或扩展名)。该标准没有定义从“指向函数的指针”到“指向void
的指针”的任何标准转换。
很难为缺席提供某些内容的引用,但我能做的最接近的是C ++ 11 4.10 / 2 [conv.ptr]:
“指向 cv
T
指针”的prvalue,“其中T
是对象类型,可以转换为prvalue键入“指针 到 cvvoid
“。将“指向 cvT
”的指针转换为“指向 cvvoid
的指针”的结果指向 类型为T
的对象所在的存储位置,就好像该对象是类型最派生的对象(1.8) T(即不是基类子对象)。空指针值转换为空指针值 目的地类型。
与3.9 / 8 [basic.types]一起:
对象类型是一种(可能是cv限定的)类型,不是函数类型,不是引用类型,而不是
void
类型。
(强调我的)
使用/Za
禁用扩展程序将禁用非标准转换。