将函数指针数组中的函数指针作为模板参数传递

Passing a function pointer from an array of function pointers as a template argument

本文关键字:函数 指针 参数传递 数组      更新时间:2023-10-16

我想将函数指针数组中的函数指针作为模板参数传递。我的代码似乎使用 MSVC 进行编译,即使智能感知抱怨出了点问题。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?
}

MSVC编译代码,但智能感知给出以下错误: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

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.

问题:

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
}

使用C++14选项编译时,以下代码片段将不起作用:

constexpr auto func = &test;
wrapper_function<func>();

当使用 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
}

观看直播