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 it A
), 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 make P
, after substitution of the deduced values (call it the deduced A
), compatible with A
.
A template type argument T
, a template template argument TT
or a template non-type argument i
can be deduced if P
and A
have 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)
TT<T>
TT<i>
TT<>
where (T)
represents argument lists where at least one argument type contains a T
, and ()
represents argument lists where no parameter contains a T
. Similarly, <T>
represents template argument lists where at least one argument contains a T
, <i>
represents template argument lists where at least one argument contains an i
and <>
represents template argument lists where no argument contains a T
or an i
.
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<i>
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<i>
, making it possible for the value of its non-type template argument to be deduced.
template<typename T, T value>
struct NonType {};
template<typename T, T value>
void f(NonType<T, value>)
{
}
void g();
struct A
{
void f();
int m;
};
int i;
#define MAKE_NONTYPE(value) NonType<decltype(value), (value)>()
int main()
{
f(MAKE_NONTYPE(0)); // NonType<int, 0>
f(MAKE_NONTYPE(&g)); // NonType<void(*)(), &g>
f(MAKE_NONTYPE(&A::f)); // NonType<void(A::*)(), &A::f>
f(MAKE_NONTYPE(&A::m)); // NonType<int A::*, &A::m>
f(MAKE_NONTYPE(&i)); // NonType<int*, &i>
}
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