Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can C++11 decltype be used to create a typedef for function pointer from an existing function?

Given

struct A {      int foo(double a, std::string& b) const; }; 

I can create a member function pointer like this:

typedef int (A::*PFN_FOO)(double, std::string&) const; 

Easy enough, except that PFN_FOO needs to be updated if A::foo's signature changes. Since C++11 introduces decltype, could it be used to automatically deduce the signature and create the typedef?

like image 274
Daniel Gehriger Avatar asked Oct 26 '12 14:10

Daniel Gehriger


People also ask

What does decltype do?

The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a template function whose return type depends on the types of its template arguments.

What does decltype return?

decltype returnsIf what we pass to decltype is the name of a variable (e.g. decltype(x) above) or function or denotes a member of an object ( decltype x.i ), then the result is the type of whatever this refers to. As the example of decltype(y) above shows, this includes reference, const and volatile specifiers.

How do you define a function pointer in C++?

We declare the function pointer, i.e., void (*ptr)(char*). The statement ptr=printname means that we are assigning the address of printname() function to ptr. Now, we can call the printname() function by using the statement ptr(s).

Why do we use typedef in C++?

We can use typedef to simplify the usage of function pointers. Imagine we have some functions, all having the same signature, that use their argument to print out something in different ways: Now we can use a typedef to create a named function pointer type called printer:

Should I use typedef names for pointer to function types?

Although using typedef names for pointer to function types makes life easier, it can also lead to confusion for others who will maintain your code later on, so use with caution and proper documentation. See also Function Pointers.

How do you use a typedef to call a function?

To use it we create a variable of the created type and assign it a pointer to one of the functions in question: Then to call the function pointed to by the function pointer variable: Thus the typedef allows a simpler syntax when dealing with function pointers.

How do you create a pointer to a function in C?

Now we can use a typedef to create a named function pointer type called printer: typedef void (*printer_t) (int); This creates a type, named printer_t for a pointer to a function that takes a single int argument and returns nothing, which matches the signature of the functions we have above.


2 Answers

Yes, of course:

typedef decltype(&A::foo) PFN_FOO;

You can also define type alias via using keyword (Thanks to Matthieu M.):

using PFN_FOO = decltype(&A::foo);

like image 140
Rost Avatar answered Sep 22 '22 12:09

Rost


One issue: you may only deduce the type of a variable if this variable is unambiguous.

The main issue with functions is that overloads mean that their names alone are insufficient to identify them. Therefore using decltype fails should you ever introduce an overload of foo in A.

struct A {     void foo() const;     void foo(int) const; };  using PFN_FOO = decltype(A::foo); 
source.cpp:6:36: error: decltype cannot resolve address of overloaded function 

Not sure you'll be gaining much thus...

On the other hand, you can actually use an alias and check that alias is right:

struct A {     void foo() const;     void foo(int) const; };  using PFN_FOO = void (A::*)(int) const;  static_assert(std::is_same<PFN_FOO, decltype(static_cast<PFN_FOO>(&A::foo))>::value,      "Ooops, need to update signature of PFN_FOO!"); 

Note: not sure this is the best way to test, basically all you need is the static_cast part, I just wanted to stash an error message alongside. You would probably need something like SFINAE to get better messages though.

like image 23
Matthieu M. Avatar answered Sep 23 '22 12:09

Matthieu M.