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

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]> }.

Nut*_*ker 5

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)

直播