函数指针作为模板参数

Function pointers as template arguments

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

在以下C++代码中,bar<func_ptr>(); //does not work行导致编译错误:

#include <iostream>
using namespace std;
void foo(){
cout<<"Hello world";
};
template<void(*func)()> 
void bar(){
(*func)();
}
int main() {
using fun_ptr_type= void(*)();
constexpr fun_ptr_type func_ptr=&foo;
bar<&foo>();     //works
bar<func_ptr>(); //does not work
return 0;
}

g++的输出是这样的:

src/main.cpp: In function ‘int main()’:
src/main.cpp:19:16: error: no matching function for call to ‘bar()’
bar<func_ptr>(); //does not work
^
src/main.cpp:10:6: note: candidate: template<void (* func)()> void bar()
void bar(){
^~~
src/main.cpp:10:6: note:   template argument deduction/substitution failed:
src/main.cpp:19:16: error: ‘(fun_ptr_type)func_ptr’ is not a valid template argument for ty
pe ‘void (*)()’
bar<func_ptr>(); //does not work
^
src/main.cpp:19:16: error: it must be the address of a function with external linkage

我不明白为什么当我直接传递foo的地址作为模板参数时它会起作用,但当我传递constexprfunc_ptr时,代码不再编译,即使它在编译时正好包含foo的地址。有人能向我解释一下吗?

编辑:我的g++版本是

$ g++ --version
g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

来源https://en.cppreference.com/w/cpp/language/template_parameters上面写着:

对于指向函数的指针,有效参数是指向具有链接的函数的指针(或求值为空指针值的常量表达式(。(直到C++17(。

由于constexpr fun_ptr_type func_ptr=&foo在编译时不会计算为nullptr值,因此如果使用-std=c++14-std=c++11运行它,它将失败。

然而,C++17对函数指针非类型模板参数没有提出这样的要求。上面写着:

可与非类型模板参数一起使用的模板参数可以是模板参数类型的任何转换常量表达式。(自C++17起(

(上面有一些例外,但没有一个适用于函数指针(。

因此,您提供的代码可以使用-std=c++17选项完美运行。