考虑这段代码:
using func = int (*)(int, int);
template<func F>
void do_something(int first, int second) {}
int something(int first, int second) { return 42; }
void f()
{
constexpr auto function = something;
do_something<function>(10, 20);
}
使用 C++17 标准兼容编译器编译和运行,但使用 C++11 标准失败: error: no matching function for call to ‘do_something<function>(int, int)’
17 | do_something<function>(10, 20);
C++11非类型模板参数和C++17非类型模板参数有什么区别?在 §14.1.4 [temp.param][n3690] 中:A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
— integral or enumeration type,
— pointer to object or pointer to function,
— lvalue reference to object or lvalue reference to function,
— pointer to member,
— std::nullptr_t.
在 §17.1.4 [temp.param][n4713] 中:
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
(4.1) — integral or enumeration type,
(4.2) — pointer to object or pointer to function,
(4.3) — lvalue reference to object or lvalue reference to function,
(4.4) — pointer to member,
(4.5) — std::nullptr_t, or
(4.6) — a type that contains a placeholder type (10.1.7.4).
唯一的区别是:
< — a type that contains a placeholder type (10.1.7.4).
我认为这与我的问题无关,因为占位符类型类似于
auto
,并且我向模板发送了一个值,而不是占位符类型或类型。
最佳答案
相关的区别在于 [temp.arg.nontype] 中允许的模板参数(不是模板参数)的要求。
C++11:
A template-argument for a non-type, non-template template-parameter shall be one of:
- ...
- a constant expression that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as
&
id-expression, except that the&
may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or- ...
C++17 :
A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
- a subobject,
- a temporary object,
- a string literal,
- the result of a
typeid
expression, or- a predefined
__func__
variable.
在 C++11 中,模板参数
function
不是 &
的形式id-expression,名称不引用函数something
.它引用了 int (*const)(int, int)
类型的变量,其值指向 something
. (而 do_something<&function>
也无济于事,因为现在你有一个指向函数的指针,它不会转换为指向函数类型的指针。)在 C++17 中,语法要求消失了,限制是对哪些对象不能指向或引用的更宽松的纯语义要求。
关于c++ - C++17和C++11中的非类型模板参数有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65077814/