Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Templates with pointer to member function by signature and type

The code below works fine but I can't figure out based what points of the C++ standard it should be valid.

template< class C, class signature >
void f(signature C::*ptr) { }

When C = A and signature = void(float, int), the function f will be

void f(void(A::*ptr)(float, int))

Based on which parts of the standard, does the template apply to the latter?

like image 805
Vorotnyak_Nazar Avatar asked May 09 '15 11:05

Vorotnyak_Nazar


1 Answers

Best go through this one by one. To avoid ambiguities, I'll use different template argument names in the example

template<class C, class signature> void f(signature C::*ptr) {}

All quotes refer to the latest working draft of the C++14 standard.

First we need to understand, how the template parameters are treated.

[temp.param]/3 A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name

So your template definition has two parameters T and the signature. When using signature in the template body, it is therefore equivalent to the typedef

typedef void signature(float, int);

This typedef may be used to declare a function pointer parameter, as in your example:

[dcl.fct]/12 A typedef of function type may be used to declare a function but shall not be used to define a function

In the parameters of the template function, you write signature T::*ptr, let's see what the standard says about member pointers:

[dcl.mptr]/1 In a declaration T D where D has the form

nested-name-specifier * attribute-specifier-seq_opt cv-qualifier-seq_opt D1

and the nested-name-specifier denotes a class, and the type of the identifier in the declaration T D1 is derived-declarator-type-list T, then the type of the identifier of D is derived-declarator-type-list cv-qualifier-seq pointer to member of class nested-name-specifier of type T.

In our example, T is signature, the function typedef, and D is C::*ptr.

This explains what types the compiler will deduce for the example

void f(void(A::*ptr)(float, int));
like image 95
user1978011 Avatar answered Sep 30 '22 00:09

user1978011