Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing object pointer as first argument for a member function: is it standard?

Tags:

c++

c++11

The following program compiles with both gcc and clang, but is this actually standard C++11 or do both compilers choose to support it for convenience?

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 is certainly convenient, but I don't understand how/why it works.

like image 200
Barry Avatar asked Nov 01 '14 19:11

Barry


People also ask

What will point to the object for which member function has been called?

The this pointer is a pointer accessible only within the nonstatic member functions of a class , struct , or union type. It points to the object for which the member function is called. Static member functions don't have a this pointer.

When pointer points to member function of the class which operator is used?

The pointer to member operators . * and ->* are used to bind a pointer to a member of a specific class object.

Can we call member function using this pointer in constructor?

the constructor is the first function which get called. and we can access the this pointer via constructor for the first time. if we are able to get the this pointer before constructor call (may be via malloc which will not call constructor at all), we can call member function even before constructor call.


1 Answers

Yes, that is standard. [func.wrap.func.inv] specifies that the operator()(ArgTypes&&... args)
of std::function calls

INVOKE (f, std::forward<ArgTypes>(args)..., R) (20.8.2), where f is the target object (20.8.1) of *this.

(Where R is the specified return type.)

[func.require] defines INVOKE:

Define INVOKE (f, t1, t2, ..., tN) as follows:

  • (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T;

  • ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item;

  • […]

Note that the trailing R in the call is used for the conversion to R (the return type of the function):

Define INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN) implicitly converted to R.

The first and only argument you give is the pointer to the Foo-object. The call to method thus results in the call (void)((*t1).*f)() which is, when written with your given values, equivalent to
((*(&myFoo)).&Foo::bar)(), which is equivalent to myFoo.bar().

like image 161
Columbo Avatar answered Oct 19 '22 05:10

Columbo