C++ typedef member function signature syntax

38.3k views Asked by At

I want to declare type definition for a member function signature. Global function typedefs look like this:

typedef int (function_signature)(int, int);
typedef int (*function_pointer) (int, int);

But I'm not able to the same thing for a member function:

typedef int (foo::memberf_signature)(int, int);   // memberf_pointer is not a member of foo
typedef int (foo::*memberf_pointer)(int, int);

It sounds logically to me, because foo:: is the syntax to access a member in the class foo.

How can I typedef just the signature?

5

There are 5 answers

11
Matthieu M. On BEST ANSWER

For questions regarding the awkward function pointer syntax, I personally use a cheat-sheet: The Function Pointers Tutorial (downloadable here, thanks to Vector for pointing it out).

The signature of a member function, however, is a bit different from the signature of a regular function, as you experienced.

As you probably know, a member function has a hidden parameter, this, whose type need be specified.

// C++11 and above.
using Member = int (Foo::*)(int, int);

// C++03 and below.
typedef int (Foo::*Member)(int, int);

does let you specify that the first element passed to the function will be a Foo* (and thus your method really takes 3 arguments, when you think of it, not just 2.

However there is another reason too, for forcing you to specify the type.

A function pointer might refer to a virtual function, in which case things can get quite complicated. Therefore, the very size of the in-memory representation changes depending on the type of function. Indeed, on Visual Studio, a function pointer's size might vary between 1 and 4 times the size of a regular pointer. This depends on whether the function is virtual, notably.

Therefore, the class the function refers to is part of the signature, and there is no work-around.

1
Mark B On

The reason it doesn't work with your current syntax is that operator precedence dictates that you're referring to a function named foo::memberf_signature, not any sort of type.

I don't know for sure if you can do this or not, but I couldn't come up with any combination of parenthese that induced the code to compile with g++ 4.2.

3
googling On

Well basically it can't work (at least I know no way using g++); Using borland c++ compiler there would be the __closure keyword.

The reason why it does not compile is, that sizeof the functionpointer (on a x86 machine) occupies always <<32bits>>; but if you want to point to a class (interface) signature, the sizeof has to be 64bit: 32 bit for the this pointer (as the class interface is in the memory only once) and 32 bit for the actual function

But the __closure keyword is a bcb language 'hack' not standardized...

2
TonyK On

It works for me:

#include <iostream>

class foo
  {
public:
  int g (int x, int y) { return x + y ; }
  } ;

typedef int (foo::*memberf_pointer)(int, int);

int main()
  {
  foo f ;
  memberf_pointer mp = &foo::g ;
  std::cout << (f.*mp) (5, 8) << std::endl ;
  }
0
Nikos Athanasiou On

You can factor out the target class in modern C++ (post 11) by utilizing the 'typedefing' qualities of template aliases. What you need would look like like:

template<typename T>
using memberf_pointer = int (T::*)(int, int); 

Yet at the point of declaration, a pointer to member function utilizing this syntax would need to specify the target class:

// D is a member function taking (int, int) and returning int
memberf_pointer<foo> mp = &foo::D;