Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ typedef member function signature syntax

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?

like image 569
0xbadf00d Avatar asked Jan 28 '11 19:01

0xbadf00d


People also ask

What is typedef declaration?

A typedef declaration is a declaration with typedef as the storage class. The declarator becomes a new type. You can use typedef declarations to construct shorter or more meaningful names for types already defined by C or for types that you have declared.

What is typedef in function pointer?

A typedef, or a function-type alias, helps to define pointers to executable code within memory. Simply put, a typedef can be used as a pointer that references a function.

Can we call member function using this pointer?

You can use pointers to member functions in the same manner as pointers to functions. You can compare pointers to member functions, assign values to them, and use them to call member functions.

Does typedef create a new type?

The typedef specifier cannot be combined with any other specifier except for type-specifiers. The typedef-names are aliases for existing types, and are not declarations of new types. Typedef cannot be used to change the meaning of an existing type name (including a typedef-name).


2 Answers

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.

like image 105
Matthieu M. Avatar answered Nov 08 '22 13:11

Matthieu M.


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; 
like image 8
Nikos Athanasiou Avatar answered Nov 08 '22 14:11

Nikos Athanasiou