【问题标题】:Passing object pointer as first argument for a member function: is it standard?将对象指针作为成员函数的第一个参数传递:它是标准的吗?
【发布时间】:2014-11-01 19:36:33
【问题描述】:

以下程序同时使用 gcc 和 clang 进行编译,但这实际上是标准 C++11 还是两个编译器都为了方便而选择支持它?

struct Foo {
    int i;

    void bar() { std::cout << i << std::endl; }
};

int main() {
    std::function<void(Foo*)> method = &Foo::bar;

    Foo myFoo{4};
    method(&myFoo); // prints 4
}

这当然很方便,但我不明白它是如何/为什么起作用的。

【问题讨论】:

  • 它与任何类成员函数指针一样工作,需要 this 来调用(只是隐藏了丑陋的东西)。你有什么特别不明白的?因为你的问题看起来有点太宽泛了。
  • 是的,这是标准的。 G++ 在这里也支持这一点:gcc.gnu.org/onlinedocs/gcc/Bound-member-functions.html
  • @πάνταῥεῖ:我认为他很好奇这似乎是标准公开this 是成员函数的参数的实现细节的地方。
  • 是的,@OliverCharlesworth 说的。
  • 相关:How do i write a pointer-to-member-function with std::function?。在其中一个答案中很好地解释了这种“魔法”如何发挥作用。

标签: c++ c++11


【解决方案1】:

是的,这是标准的。 [func.wrap.func.inv] 指定operator()(ArgTypes&amp;&amp;... args)
std::function 调用

INVOKE (f, std::forward&lt;ArgTypes&gt;(args)..., R) (20.8.2),其中 f*this 的目标对象 (20.8.1)。

(其中R是指定的返回类型。)

[func.require] 定义INVOKE

定义INVOKE (f, t1, t2, ..., tN)如下:

  • (t1.*f)(t2, ..., tN)f 是指向类T 的成员函数的指针并且t1T 类型的对象或对 T 类型的对象或对派生自的类型的对象的引用 T;

  • ((*t1).*f)(t2, ..., tN)f 是一个指向类T 的成员函数的指针并且t1 不是中描述的类型之一 上一项;

  • […]

请注意,调用中尾部的R 用于转换为Rfunction 的返回类型):

INVOKE (f, t1, t2, ..., tN, R) 定义为 INVOKE (f, t1, t2, ..., tN) 隐式转换为 R

您给出的第一个也是唯一一个参数是指向Foo-object 的指针。因此,对method 的调用会导致调用(void)((*t1).*f)(),当使用给定值写入时,它相当于
((*(&amp;myFoo)).&amp;Foo::bar)(),它相当于myFoo.bar()

【讨论】:

  • 遗憾的是,他们没有在定义函数 std::invoke 时...
  • @Deduplicator 好吧,它的实现或多或少是微不足道的——人们必须通过基于优先级的重载解决机制来考虑排名,但 libstdc++ IIRC 中有一个错误的实现。
  • 什么什么!您也可以将函数指向成员数据吗? (std::function&lt;int&amp;(Foo&amp;)&gt; data = &amp;Foo::i;) 伙计,我今天正在学习各种各样的东西。
  • @Barry 是的,包含在相同的引号中。
  • @Deduplicator 迟到几年总比没有好?
猜你喜欢
  • 2017-03-17
  • 2013-06-29
  • 2020-06-09
  • 2013-08-11
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多