C++ allows non-type template parameters to be of pointer, including function pointer, type. I recently asked a question about what this is useful for, and this is a follow u
Template arguments for a function are deduced from the types of the function's template parameters. Template arguments can only be deduced from a type when that type is one of the allowed forms. The allowed forms are specified in [temp.deduct.type]
Template arguments can be deduced in several different contexts, but in each case a type that is specified in terms of template parameters (call it
P) is compared with an actual type (call itA), and an attempt is made to find template argument values (a type for a type parameter, a value for a non-type parameter, or a template for a template parameter) that will makeP, after substitution of the deduced values (call it the deducedA), compatible withA.A template type argument
T, a template template argumentTTor a template non-type argumentican be deduced ifPandAhave one of the following forms:
T cv-list T T* T& T[integer-constant] template-name (where template-name refers to a class template) type(*)(T) T(*)() T(*)(T) T type::* type T::* T T::* T (type::*)() type (T::*)() type (type::*)(T) type (T::*)(T) T (type::*)(T) T (T::*)() T (T::*)(T) type[i] template-name<i> (where template-name refers to a class template) TTTT TT<>
where
(T)represents argument lists where at least one argument type contains aT, and()represents argument lists where no parameter contains aT. Similarly,represents template argument lists where at least one argument contains aT,represents template argument lists where at least one argument contains aniand<>represents template argument lists where no argument contains aTor ani.
When considering only non-type template arguments, the relevant forms are those that contain i:
type[i] template-name<i> (where template-name refers to a class template) TT
Therefore it is not possible to deduce the value directly from the value of a function argument that is the function pointer. However it is possible to deduce the value of a non-type template argument if the function parameter has one of the specified forms.
The following code ahieves this by wrapping the non-type template argument value in a class-template called NonType. The parameter of f is in the form template-name, making it possible for the value of its non-type template argument to be deduced.
template
struct NonType {};
template
void f(NonType)
{
}
void g();
struct A
{
void f();
int m;
};
int i;
#define MAKE_NONTYPE(value) NonType()
int main()
{
f(MAKE_NONTYPE(0)); // NonType
f(MAKE_NONTYPE(&g)); // NonType
f(MAKE_NONTYPE(&A::f)); // NonType
f(MAKE_NONTYPE(&A::m)); // NonType
f(MAKE_NONTYPE(&i)); // NonType
}
Note that decltype and the MAKE_NON_TYPE macro are used here only as a convenience, to avoid having to write out the full template argument list of NonType