Reputation: 914
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?
Upvotes: 6
Views: 855
Reputation: 3589
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
whereD
has the formnested-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 ofD
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));
Upvotes: 5