在下面的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.
答案 0 :(得分:10)
在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
选项完美运行。