[英]C++ dereference happens after implicit conversion
今天,我看到尝试在函数调用中取消引用参数时,隐式转换发生在实际的取消引用操作之前(我相信只有在原始类型不支持取消引用的情况下)。
可以在这里看到此观察结果:
struct A{};
struct C
{
C(const A&)
{
}
};
C operator*(const C&);
double f(C);
template <typename T>
struct t
{
static const bool value = sizeof(f(**static_cast<T*>(NULL))) == sizeof(double);
};
int main(int argc, const char * argv[]) {
t<A>::value;
}
C ++标准是否明确提到了此行为? 谢谢。
让我们看一下这个表达式:
f(**static_cast<A*>(NULL))
从最内层到最外层, static_cast<A*>(NULL)
std::declval<A*>()
static_cast<A*>(NULL)
是一个A*
(尽管更喜欢nullptr
而std::declval<A*>()
NULL
,并且还更喜欢使用std::declval<A*>()
获得“类型为A*
东西”,而不是老式的空指针方法转换)。
接下来, *(a prvalue of type A*)
为您提供类型为A
的左值。 这就是指针取消引用的含义,并且它不可重载。 事情容易推理的时候很好。
接下来, *(an lvalue of type A)
。 为了弄清楚这意味着什么,我们将调用转换为函数符号,我们的候选集是:
A::operator*()
operator*(a)
,在表达式的上下文中对operator*()
进行无限定的查找。 第一个项目符号什么也找不到,没有A::operator*()
。 第二个项目符号,即对operator*()
无限定查找将找到函数C operator*(const C&);
因为它在范围内。 这是一个可行的候选人,因为A
可以通过C(A const&)
转换为C
第三个子弹没有可行的候选人。
由于我们只有一个可行的候选者,因此它是最佳可行的候选者-因此*(lvalue of type A)
提供了C
类型的prvalue。
具体回答您的问题:
隐式转换发生在实际的取消引用操作之前
是的,必须进行转换才能解决取消引用操作。 尽管实际上不是“取消引用”,但它只是一元运算operator*()
。
最后, f(prvalue of type C)
调用我们拥有的f
,它使我们获得double
。
请注意,在现代C ++中,我建议将支票写得更接近:
template <typename T>
struct t
: std::is_same<
decltype(f(*std::declval<T>())), // <== the type we get when we call f
// on a dereferenced T
double>
{ };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.