匹配bool的函数的地址vs const void * overload [英] The address of a function matching a bool vs const void* overload
问题描述
我正在阅读意外值使用随机数生成器作为函数在C ++ 和注释和当前答案说,用户正在输出的函数的地址。听起来合情合理。我假设发生了一个函数到指针转换,因此匹配 const void *
重载,但是当我自己测试时,导致GCC / Clang与MSVC。以下测试程序:
I'm reading Unexpected value using random number generator as a function in C++ and the comments and current answer say that the user is outputting the address of the function. That sounded reasonable. I assumed that a function-to-pointer conversion was occurring and therefore matching the const void*
overload, however upon testing it myself, I get different results in GCC/Clang vs MSVC. The following test program:
#include <iostream>
void test()
{
}
void func(bool)
{
std::cout << "bool";
}
void func(const void*)
{
std::cout << "const void*";
}
int main()
{
func(test);
}
输出 bool
GCC / Clang( coliru
outputs bool
in GCC/Clang (coliru
)
和 const void *
http://rextester.com/live/QNFXT35340rel =nofollow> rextester
警告实时协作链接)
and const void*
in MSVC (rextester
warning live collaboration link)
N3337 说:
[conv.func]
[conv.func]
的函数类型
T
可以转换为
类型的prvalue指向T
。结果是指向该函数的指针。
An lvalue of function type
T
can be converted to a prvalue of type "pointer toT
." The result is a pointer to the function.
[conv.bool]
[conv.bool]
可以将算术,无范围枚举,指针或指向
成员类型的prval值转换为 bool 。零
值,空指针值或空成员指针值将
转换为 false
;任何其他值将转换为 true
。
std :: nullptr_t
类型的prval值可以转换为bool类型的prvalue;
的结果值是 false
。
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type
bool
. A zero value, null pointer value, or null member pointer value is converted tofalse
; any other value is converted totrue
. A prvalue of typestd::nullptr_t
can be converted to a prvalue of type bool; the resulting value isfalse
.
不是空指针值转换为bool应等于 true
,解释由GCC / Clang给出的警告。
So a pointer which is not a null pointer value converted to bool should equal true
, explaining the warning given by GCC/Clang.
然后表12 [over.ics.scs]下的转换提供了一个函数到指针的转换,完全匹配排名和布尔转换转换排名。 [over.ics.rank] / 4然后说:
Then Table 12 Conversions under [over.ics.scs] gives a function-to-pointer conversion an "Exact Match" rank and boolean conversions "Conversion" rank. [over.ics.rank]/4 then says:
标准转换序列按其排名排序:an Exact
Match是一种更好的转化,而不是促销,这是比转化更好的
转化。具有相同
排名的两个转换序列是无法区分的,除非以下规则之一适用:
Standard conversion sequences are ordered by their ranks: an Exact Match is a better conversion than a Promotion, which is a better conversion than a Conversion. Two conversion sequences with the same rank are indistinguishable unless one of the following rules applies:
一个指针,指向成员的指针,
或std :: nullptr_t
到bool
- [...]
— [...]
$ b b
我不是一个语言律师,所以我希望我引用正确的部分。
I am not a language lawyer so I hope that I quoted the right sections.
然而MSVC会调用 const void *
重载,即使 bool
overload不存在,反之亦然:GCC / Clang将调用 bool
重载,即使 const void *
重载不存在。所以我不清楚在这里的转换。
However MSVC will call the const void*
overload even if the bool
overload is absent, and vice versa: GCC/Clang will call the bool
overload even if the const void*
overload is absent. So I'm not clear on the conversions here. Can somebody clear this up for me?
推荐答案
看起来像MSVC中的错误(或扩展名)。该标准没有定义从指针到函数到指向 void
的任何标准转换。
Seems like a bug (or extension) in MSVC. The standard does not define any standard conversions from a "pointer to function" to a "pointer to void
."
很难为某事的缺席提供报价,但我能做的最接近的是C ++ 11 4.10 / 2 [conv.ptr]:
It's hard to provide a quote for the absence of something, but the closest I can do is C++11 4.10/2 [conv.ptr]:
指向 cv
T
,的类型的prvalue $ c> T 是一个对象类型,可以转换为类型为指针
到 cv的prvalue
。将指向 cvT
的指针转换为指向 cvvoid
指向
的开始位置T
类型的对象所在的存储位置,就像对象是最大派生
T类型的对象(1.8)(即不是基类子对象)。空指针值将转换为
目标类型的空指针值。
A prvalue of type "pointer to cv
T
," whereT
is an object type, can be converted to a prvalue of type "pointer to cvvoid
". The result of converting a "pointer to cvT
" to a "pointer to cvvoid
" points to the start of the storage location where the object of typeT
resides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject). The null pointer value is converted to the null pointer value of the destination type.
与3.9 / 8 .types]:
Together with 3.9/8 [basic.types]:
对象类型是(可能是cv限定的)不是函数类型,而不是引用类型,而不是
void
类型。
An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not a
void
type.
(强调我)
使用 / Za
禁用扩展将禁用非标准转换。
Using /Za
to disable extensions will disable the non-standard conversion.
这篇关于匹配bool的函数的地址vs const void * overload的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!