函数指针作为模板参数

Function pointers as template arguments

在以下 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 的地址作为模板参数传递时它会起作用,但是当我传递 constexpr func_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 它说:

For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values). (until C++17).

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

然而,C++17 对函数指针非类型模板参数没有这样的要求。它说:

The template argument that can be used with a non-type template parameter can be any converted constant expression of the type of the template parameter. (since C++17)

(上述情况有一些例外,但 none 适用于函数指针)。

所以您提供的代码 运行 与 -std=c++17 选项完美匹配。