Mat*_*tti 10 c++ templates c++14
我想将函数指针数组中的函数指针作为模板参数传递。我的代码似乎使用 MSVC 编译,即使 Intellisense 抱怨出现问题。gcc 和 clang 都无法编译代码。
考虑以下示例:
static void test() {}
using FunctionPointer = void(*)();
static constexpr FunctionPointer functions[] = { test };
template <FunctionPointer function>
static void wrapper_function()
{
function();
}
int main()
{
test(); // OK
functions[0](); // OK
wrapper_function<test>(); // OK
wrapper_function<functions[0]>(); // Error?
}
Run Code Online (Sandbox Code Playgroud)
MSVC编译代码,但 Intellisense 给出以下错误:invalid nontype template argument of type "const FunctionPointer"
gcc无法编译并显示以下消息:
<source>: In function 'int main()':
<source>:19:33: error: no matching function for call to 'wrapper_function<functions[0]>()'
19 | wrapper_function<functions[0]>(); // Error?
| ^
<source>:8:13: note: candidate: 'template<void (* function)()> void wrapper_function()'
8 | static void wrapper_function()
| ^~~~~~~~~~~~~~~~
<source>:8:13: note: template argument deduction/substitution failed:
<source>:19:30: error: '(FunctionPointer)functions[0]' is not a valid template argument for type 'void (*)()'
19 | wrapper_function<functions[0]>(); // Error?
| ~~~~~~~~~~~^
<source>:19:30: note: it must be the address of a function with external linkage
Run Code Online (Sandbox Code Playgroud)
clang无法编译并显示以下消息:
<source>:19:2: error: no matching function for call to 'wrapper_function'
wrapper_function<functions[0]>(); // Error?
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:8:13: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'function'
static void wrapper_function()
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
问题:
是否wrapper_function<functions[0]>();有效?
如果不是,我可以做些什么来functions[0]作为模板参数传递给wrapper_function?我的目标是在编译时构造一个新的函数指针数组,内容为{ wrapper_function<functions[0]>, ..., wrapper_function<functions[std::size(functions) - 1]> }.
wrapper_function<functions[0]>();由于以下原因,禁止表达:
14.3.2 模板非类型参数 [temp.arg.nontype]
非类型、非模板模板参数的模板参数应为以下之一:
[...]
— 一个常量表达式 (5.19),它指定一个对象的地址,具有静态存储 > 持续时间和外部或内部链接,或者一个具有外部或内部链接的函数,包括函数模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号)作为& id-expression,除了如果名称指的是函数或数组,则可以省略&,如果相应的模板参数是引用,则应省略; [...]
禁止使用指针作为非类型模板参数而不是形式,&id因此,基本上,以下将起作用:
static void test() {}
using FunctionPointer = void(*)();
static constexpr FunctionPointer functions[] = { test };
template <FunctionPointer function>
static void wrapper_function()
{
function();
}
int main()
{
test(); // OK
functions[0](); // OK
wrapper_function<test>(); // OK
wrapper_function<&test>(); // OK
}
Run Code Online (Sandbox Code Playgroud)
使用 C++14 选项编译时,以下代码段将不起作用:
constexpr auto func = &test;
wrapper_function<func>();
Run Code Online (Sandbox Code Playgroud)
当使用 C++17 选项编译时,你的方法和上面的方法都可以工作:
int main()
{
test(); // OK
functions[0](); // OK
wrapper_function<test>(); // OK
wrapper_function<&test>(); // OK
wrapper_function<func>(); // OK
wrapper_function<functions[0]>(); // OK
}
Run Code Online (Sandbox Code Playgroud)
看直播