有没有办法推断出函数指针模板参数的值? [英] Is there a way to deduce the value of a function pointer template parameter?
问题描述
C ++允许非类型模板参数为指针,包括函数指针,类型。我最近询问了一个问题,了解此功能的用途,这是其中一个答案的后续步骤。
是否可以从函数指针的函数参数中推导出函数指针模板参数的值?例如:
使用VoidFunction = void(*)();
template< VoidFunction F>
void templ(VoidFunction);
...
void func(); // a VoidFunction
...
templ< func>(func); //工作,但我必须明确指定模板参数
templ(func); //< - 我想能够做到这一点
这个扣除发生?从编译器实现者的角度看,只要函数参数可以在编译时解析为代码中的函数,这在技术上似乎是可能的。
如果你想知道背后的动机,请参阅此答案下的注释,特别是可能的优化实施 std :: bind()
。
EDIT :我意识到我可以简单地删除函数参数并使用模板参数,如 templ< func>()
中所示。我添加在函数参数的唯一目的是试图避免传递模板参数。
我想我真正想要的是,还推导 type ,如下所示:
template< typename Function,Function F&
void templ(/ * something * /);
,然后才能呼叫
templ(func);
或
templ< func>();
,并且从单一提及函数指针中推导出类型和值。
希望现在更有意义。
函数的模板参数从函数的模板参数的类型推导出。仅当该类型是允许的表单之一时,才能从类型中推导出模板参数。允许的表单在[temp.deduct.type]中指定
模板参数可以在几种不同的上下文中推导出来,在模板参数(调用
P
)中指定的类型与实际类型(调用A
),并尝试查找模板参数值(类型参数的类型,非类型参数的值或模板参数的模板),这将使P
,替换推导的值(称为推导A
),与A
兼容。 / p>
模板类型参数
T
,模板模板参数TT
P 和A 可以推导出或者模板非类型参数
i
code>有以下形式之一:
T
cv-list T
T *
T&
T [整数常数]
模板名称(其中模板名称指类模板)
类型(*)(T)
T(*)()
T(*)(T)
T类型:: *
类型T :: *
TT :: *
T类型:: *)()
类型(T :: *)()
类型(类型:: *)(T)
类型$ b T(type :: *)(T)
T(T :: *)()
T(T :: *)(T)
type [i]
template-name<>(其中template-name指类模板)
TT
TT
TT
其中
(T)
表示参数列表,其中至少一个参数类型包含/ code>,
()
表示没有参数包含T
的参数列表。类似地,< T>
表示模板参数列表,其中至少一个参数包含T
,< i>
代表至少一个参数包含i
和< code>表示模板参数列表,其中没有参数包含
T
或i
。
当只考虑非类型模板参数时,相关的形式是包含
i
:type [i]
template-name<>(其中template-name指类模板)
TT pre>
因此,不可能从作为函数指针的函数参数的值直接推导出值。但是,如果函数参数具有指定形式之一, 可以推断非类型模板参数的值。
以下代码通过将非类型模板参数值包装在名为
NonType
的类模板中来实现。f
的参数是template-name< i>
的形式,模板< 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>
}
注意
decltype
和MAKE_NON_TYPE
宏在这里只是为了方便,以避免写出NonType
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 up to one of the answers.
Is it posible to deduce the value of a function pointer template parameter, from a function argument that is the function pointer in question? For example:
using VoidFunction = void(*)(); template <VoidFunction F> void templ(VoidFunction); ... void func(); // a VoidFunction ... templ<func>(func); // works, but I have to specify the template parameter explicitly templ(func); // <-- I would like to be able to do this
Is there a way to get this deduction to happen? It seems technically possible from a compiler implementer's point of view, as long as the function argument can be resolved to a function in the code at compile time.
If you're wondering about the motivation behind this, see the comments under this answer, particularly a possible optimization for the implementation of
std::bind()
.EDIT: I realize that I could simply remove the function argument and use the template argument, as in
templ<func>()
. My only purpose of adding in the function argument was to try to avoid having to pass the template argument.I guess what I really want, is to also deduce the type of the function pointer, as in:
template <typename Function, Function F> void templ(/* something */);
and then be able to call
templ(func);
or
templ<func>();
and have both the type and value be deduced from a single mention of the function pointer.
Hope that makes more sense now.
解决方案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 argumentTT
or a template non-type argumenti
can be deduced ifP
andA
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 aT
, and()
represents argument lists where no parameter contains aT
. Similarly,<T>
represents template argument lists where at least one argument contains aT
,<i>
represents template argument lists where at least one argument contains ani
and<>
represents template argument lists where no argument contains aT
or 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<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 off
is in the formtemplate-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 theMAKE_NON_TYPE
macro are used here only as a convenience, to avoid having to write out the full template argument list ofNonType
这篇关于有没有办法推断出函数指针模板参数的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!