gpt4 book ai didi

c++ - 为什么 [expr.ref]p(6.3.2) 中的句子 "The expression can be used only as the left-hand operand of a member function call"?

转载 作者:太空狗 更新时间:2023-10-29 20:50:07 25 4
gpt4 key购买 nike

[expr.ref]p(6.3.2) :

Otherwise, if E1.E2 refers to a non-static member function and the type of E2 is “function of parameter-type-list cv ref-qualifieropt returning T”, then E1.E2 is a prvalue. The expression designates a non-static member function. The expression can be used only as the left-hand operand of a member function call ([class.mfct]). [ Note: Any redundant set of parentheses surrounding the expression is ignored ([expr.prim.paren]). — end note ] The type of E1.E2 is “function of parameter-type-list cv returning T”.



例如 main 中的第二个语句下面没有编译,可能是因为上面突出显示的句子。但是为什么语言被设置为以这种方式工作?
#include<iostream>
void g();
struct S { void f(); };
S s;

int main(){
std::cout << "decltype(g) == void() ? " << std::is_same<decltype(g), void()>::value << '\n'; // Ok
std::cout << "decltype(s.f) == void() ? " << std::is_same<decltype(s.f), void()>::value << '\n'; // Doesn't compile probably because of the sentence hihlighted above in [expr.ref]p(6.3.2).
}

最佳答案

当您这样做时E1.E2 ,您不是在谈论 E1 类型的事物的一般属性是。您要求访问由 E1 指定的对象内的事物。 ,其中要访问的事物的名称是E2 .如 E2是静态的,它访问类静态的东西;如果 E2是非静态的,然后它访问特定于该对象的成员事物。这很重要。

成员变量成为子对象。如果您的类(class) S有一个非静态数据成员 int i; , s.i是对 int 的引用.从 int& 的角度来看,该引用文献, 的行为与任何其他 int& 没有什么不同.

让我更清楚地说:任何 int*int&可以指向/引用 int这是一个完整的对象或 int它是某个其他对象的子对象。单个构造 int&可以以这种方式履行双重职责。 *

鉴于对s.i的理解,s.f 的假定含义是什么? ?嗯,应该差不多吧? s.f当用 params 调用时会是某种东西, 相当于做 s.f(params) .

但这不是 C++ 中存在的东西。

C++ 中没有语言结构可以表示 s.f 的含义。 .这样的构造需要存储对 s 的引用。以及成员(member)S::f .

函数指针不能这样做。函数指针需要能够与 void* 指针相互转换**。但是这样的s.f将需要存储成员 S::f以及对 s 的引用本身。所以根据定义,它必须大于 void* .

成员指针也不能这样做。成员指针明确不携带它们的 this对象和他们一起(这就是重点);您必须在调用时使用特定成员指针调用语法提供它们 .*.-> .

哦,有一些方法可以在语言中对此进行编码:lambdas,std::bind等。但是没有具有这种精确含义的语言级构造。

因为C++在这种方式上是不对称的,其中s.i具有可编码的意义但不是 s.f , C++ 使不可编码的非法。

您可能会问为什么这样的构造不能简单地构建。其实没那么重要。由于 s.f 的复杂性,该语言可以正常工作。需要的是,如果这是您想要的,最好让您使用 lambda(无可否认,应该有办法缩短编写此类内容的时间)。

如果你想要一个裸体 s.f相当于 S::f (即:指定成员函数),这也不起作用。一、S::f也没有类型;您可以对这样的纯右值做的唯一事情是将其转换为指向成员的指针。其次,成员函数指针不知道它来自哪个对象,所以为了使用一个来调用成员,你需要给它s .因此,在调用表达式中,s必须出现两次。这真的很愚蠢。

*:有些事情你可以做来完成对象,而你不能对子对象做。但是那些会引起 UB,因为它们无法被编译器检测到,因为 int*没有说它是否来自子对象。这是重点;没有人能分辨出其中的区别。

**:标准不要求这样做,但标准不能做一些使这种实现不可能的事情。大多数实现都提供此功能,基本上任何 DLL/SO 加载代码都依赖于它。哦,它也将与 C 完全不兼容,这使得它无法入门。

关于c++ - 为什么 [expr.ref]p(6.3.2) 中的句子 "The expression can be used only as the left-hand operand of a member function call"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56409433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com