HC4*_*ica 6 c++ templates non-type template-argument-deduction
C++允许非类型模板参数为指针,包括函数指针,类型.最近,我问了一个问题,什么这是有用的,这是一个后续行动的答案之一.
从作为函数指针的函数参数中推导出函数指针模板参数的值是否可行?例如:
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
Run Code Online (Sandbox Code Playgroud)
有没有办法让这种演绎发生?从编译器实现者的角度来看,技术上似乎是可能的,只要函数参数可以在编译时解析为代码中的函数.
如果您想知道这背后的动机,请参阅此答案下的评论,特别是可能的实施优化std::bind().
编辑:我意识到我可以简单地删除函数参数并使用模板参数,如templ<func>().添加函数参数的唯一目的是尽量避免传递模板参数.
我想我真正想要的是,还推断出函数指针的类型,如:
template <typename Function, Function F>
void templ(/* something */);
Run Code Online (Sandbox Code Playgroud)
然后就可以打电话了
templ(func);
Run Code Online (Sandbox Code Playgroud)
要么
templ<func>();
Run Code Online (Sandbox Code Playgroud)
并且只需提及函数指针就可以推导出类型和值.
希望现在更有意义.
函数的模板参数是从函数模板参数的类型推导出来的。仅当该类型是允许的形式之一时,才能从该类型推导模板参数。允许的形式在 [temp.deduct.type] 中指定
可以在几种不同的上下文中推导模板参数,但在每种情况下,都会将根据模板参数指定的类型(称为
P)与实际类型(称为A)进行比较,并尝试查找模板参数值(类型参数的类型、非类型参数的值或模板参数的模板),P在替换推导值(称为推导的A)后,将使 与 兼容A。如果且具有以下形式之一,则可以推导出模板类型实参
T、模板模板实参TT或模板非类型实参:iPA
时间 简历列表 T 时间* 特& T[整数常数] 模板名称(其中模板名称指类模板) 类型(*)(T) T(*)() T(*)(T) T型::* 类型 T::* TT::* T(类型::*)() 类型 (T::*)() 类型(类型::*)(T) 类型 (T::*)(T) T(类型::*)(T) T (T::*)() T (T::*)(T) 类型[i] template-name<i> (其中 template-name 指的是类模板) TT<T> TT<i> TT<>
其中
(T)表示参数列表,其中至少一个参数类型包含 aT,并()表示参数列表,其中没有参数包含 aT。类似地,<T>表示模板参数列表,其中至少一个参数包含 aT,<i>表示模板参数列表,其中至少一个参数包含 ai,<>表示模板参数列表,其中没有参数包含 aT或 ani。
当仅考虑非类型模板参数时,相关形式是包含以下内容的形式i:
类型[i] template-name<i> (其中 template-name 指的是类模板) TT<i>
因此,不可能直接从函数参数(即函数指针)的值推导出该值。但是,如果函数参数具有指定形式之一,则可以推断出非类型模板参数的值。
以下代码通过将非类型模板参数值包装在名为 的类模板中来实现此目的NonType。的参数f采用 的形式template-name<i>,使得可以推导出其非类型模板实参的值。
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>
}
Run Code Online (Sandbox Code Playgroud)
请注意,此处使用decltype和MAKE_NON_TYPE宏只是为了方便,以避免必须写出完整的模板参数列表NonType