【问题标题】:Passing a function pointer from an array of function pointers as a template argument将函数指针数组中的函数指针作为模板参数传递
【发布时间】:2020-01-17 13:13:55
【问题描述】:

我想将函数指针数组中的函数指针作为模板参数传递。即使 Intellisense 抱怨有问题,我的代码似乎也可以使用 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 编译代码,但 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

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&lt;functions[0]&gt;(); 是否有效?

如果不是,我可以做些什么来将functions[0] 作为模板参数传递给wrapper_function?我的目标是在编译时构造一个新的函数指针数组,内容为{ wrapper_function&lt;functions[0]&gt;, ..., wrapper_function&lt;functions[std::size(functions) - 1]&gt; }

【问题讨论】:

  • 嗯,这很有趣,我认为问题在于您使用的是值(指针)而不是类型。但即使wrapper_function&lt;decltype(functions[0])&gt;() 也无法编译。
  • 似乎可以在 C++17 中工作...现在来寻找标准语言的区别...

标签: c++ templates c++14


【解决方案1】:

表达式wrapper_function&lt;functions[0]&gt;(); 被禁止,原因如下:

14.3.2 模板非类型参数 [temp.arg.nontype]

非类型、非模板模板参数的模板参数 应为以下之一:

[...]

——一个常量表达式(5.19),指定一个地址 具有静态存储 > 持续时间和外部或内部链接的对象 或具有外部或内部链接的功能,包括功能 模板和函数模板 ID,但不包括非静态类 成员,表示(忽略括号)为 & id-expression,除了 如果名称引用函数或数组,则 & 可以省略 如果相应的模板参数是 参考; [...]

禁止将指针用作&amp;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 选项编译时,以下 sn-p 将不起作用:

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
}

live

【讨论】:

  • C++17 将其替换为“converted constant expression”,即它允许链接常量表达式,因此wrapper_function&lt;func&gt;() 也可以工作。
  • Ok 将在我完整写完答案后检查并更新答案。 Tnx
猜你喜欢
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 2022-01-20
  • 2011-08-01
  • 2020-11-08
相关资源
最近更新 更多