Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the function signature of a member function?

I'm having trouble understanding function signatures and pointers.

struct myStruct
{
    static void staticFunc(){};
    void nonstaticFunc(){};
};

int main()
{
    void (*p)();     // Pointer to function with signature void();
    p = &myStruct::staticFunc;    // Works fine
    p = &myStruct::nonstaticFunc; // Type mismatch   
}

My compiler says that the type of myStruct::nonstaticFunc() is void (myStruct::*)(), but isn't that the type of a pointer pointing to it?

I'm asking because when you create an std::function object you pass the function signature of the function you want it to point to, like:

std::function<void()> funcPtr;      // Pointer to function with signature void()
not 
std::function<void(*)()> funcPtr;

If I had to guess based on the pattern of void() I would say:

void myStruct::();
or
void (myStruct::)();

But this isn't right. I don't see why I should add an asterisk just because it's nonstatic as opposed to static. In other words, pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?

like image 534
Zebrafish Avatar asked Dec 26 '16 06:12

Zebrafish


People also ask

What is the function of a signature?

The traditional function of a signature is to permanently affix to a document a person's uniquely personal, undeniable self-identification as physical evidence of that person's personal witness and certification of the content of all, or a specified part, of the document.

What is a signature of a function in C++?

C++ Reference. Programming Terms. Function Signatures. A function signature consists of the function prototype. What it tells you is the general information about a function, its name, parameters, what scope it is in, and other miscellaneous information.

How do you find the signature of a function?

We can get function Signature with the help of signature() Function. It takes callable as a parameter and returns the annotation. It raises a value Error if no signature is provided. If the Invalid type object is given then it throws a Type Error.

What are the parts of a function signature?

A function's signature includes the function's name and the number, order and type of its formal parameters. Two overloaded functions must not have the same signature. The return value is not part of a function's signature.


2 Answers

To me there seems to be a basic misunderstanding of what a member pointer is. For example if you have:

struct P2d {
    double x, y;
};

the member pointer double P2d::*mp = &P2d::x; cannot point to the x coordinate of a specific P2d instance, it is instead a "pointer" to the name x: to get the double you will need to provide the P2d instance you're looking for... for example:

P2d p{10, 20};

printf("%.18g\n", p.*mp); // prints 10

The same applies to member functions... for example:

struct P2d {
    double x, y;
    double len() const {
        return sqrt(x*x + y*y);
    }
};

double (P2d::*f)() const = &P2d::len;

where f is not a pointer to a member function of a specific instance and it needs a this to be called with

printf("%.18g\n", (p.*f)());

f in other words is simply a "selector" of which of the const member functions of class P2d accepting no parameters and returning a double you are interested in. In this specific case (since there is only one member function compatible) such a selector could be stored using zero bits (the only possible value you can set that pointer to is &P2d::len).

Please don't feel ashamed for not understanding member pointers at first. They're indeed sort of "strange" and not many C++ programmers understand them.

To be honest they're also not really that useful: what is needed most often is instead a pointer to a method of a specific instance.

C++11 provides that with std::function wrapper and lambdas:

std::function<double()> g = [&](){ return p.len(); };

printf("%.18g\n", g()); // calls .len() on instance p
like image 189
6502 Avatar answered Sep 20 '22 09:09

6502


std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);

Is how you store a member function in std::function. The member function must be called on a valid object.


If you want to delay the passing of an object until later, you can accomplish it like this:

#include <functional>
#include <iostream>

struct A {

    void foo() { std::cout << "A::foo\n"; }
};

int main() {
    using namespace std::placeholders;

    std::function<void(A&)> f = std::bind(&A::foo, _1);

    A a;
    f(a);

    return 0;
}

std::bind will take care of the details for you. std::function still must have the signature of a regular function as it's type parameter. But it can mask a member, if the object is made to appear as a parameter to the function.


Addenum:
For assigning into std::function, you don't even need std::bind for late binding of the object, so long as the prototype is correct:

std::function<void(A&)> f = &A::foo;
like image 31
StoryTeller - Unslander Monica Avatar answered Sep 19 '22 09:09

StoryTeller - Unslander Monica