自动模板参数可以传什么有限制吗?
Are There Restrictions on What can be Passed to auto Template Parameters?
在c++17 we got auto
template parameters. I was trying to use one to pass an object in this question: But directed by 中我发现没有编译:(
给定模板函数:
template <auto T>
void foo()
我可以作为模板参数传递的内容似乎受到限制。例如,如我的链接问题所示,我似乎无法传递函子:
foo<plus<int>{}>()
是否有允许和不允许的列表?
我相信这完全由以下标准语句处理:
[temp.arg.nontype]
1:
If the type T of a template-parameter ([temp.param]) contains a placeholder type ([dcl.spec.auto]) or a placeholder for a deduced class type ([dcl.type.class.deduct]), the type of the parameter is the type deduced for the variable x in the invented declaration
T x = template-argument ;
If a deduced parameter type is not permitted for a template-parameter declaration ([temp.param]), the program is ill-formed.
允许传递函子类型。传递仿函数实例不是,就像传递 struct A {};
的实例不是。
至于允许使用哪些非类型模板参数:
4:
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
(4.1)
a type that is literal, has strong structural equality ([class.compare.default]), has no mutable or volatile subobjects, and in which if there is a defaulted member operator<=>, then it is declared public,
(4.2)
an lvalue reference type,
(4.3)
a type that contains a placeholder type ([dcl.spec.auto]), or
(4.4)
a placeholder for a deduced class type ([dcl.type.class.deduct]).
5:
[ Note: Other types are disallowed either explicitly below or implicitly by the rules governing the form of template-arguments ([temp.arg]).
— end note
]
The top-level cv-qualifiers on the template-parameter are ignored when determining its type.
在 C++17 中,可以在 [temp.param]/4:
中找到限制
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
, or
- a type that contains a placeholder type.
对 [temp.arg.nontype]/2 中的参数有额外限制:
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.
您出错的地方是 std::plus<int>
不是有效的非类型模板参数。它是第一个列表中那些东西的 none。
在C++20中,可用作非类型模板参数的类型种类将大大扩展。我们将能够使用 class 类型作为非类型模板参数,前提是那些 class 类型满足称为 "strong structural equality." 的东西,在当前草案中,这是根据 [=36= 定义的],默认operator<=>
。在 P1185 中,目前正在开发中,可能会被采用,它会略有变化,以 public 的形式定义,默认为 operator==
.
但即使在 C++20 中,std::plus<int>
实际上也没有定义任何比较运算符 - 因此您仍然无法将其用作非类型模板参数。
在c++17 we got auto
template parameters. I was trying to use one to pass an object in this question:
给定模板函数:
template <auto T>
void foo()
我可以作为模板参数传递的内容似乎受到限制。例如,如我的链接问题所示,我似乎无法传递函子:
foo<plus<int>{}>()
是否有允许和不允许的列表?
我相信这完全由以下标准语句处理:
[temp.arg.nontype]
1: If the type T of a template-parameter ([temp.param]) contains a placeholder type ([dcl.spec.auto]) or a placeholder for a deduced class type ([dcl.type.class.deduct]), the type of the parameter is the type deduced for the variable x in the invented declarationT x = template-argument ;
If a deduced parameter type is not permitted for a template-parameter declaration ([temp.param]), the program is ill-formed.
允许传递函子类型。传递仿函数实例不是,就像传递 struct A {};
的实例不是。
至于允许使用哪些非类型模板参数:
4: A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
(4.1) a type that is literal, has strong structural equality ([class.compare.default]), has no mutable or volatile subobjects, and in which if there is a defaulted member operator<=>, then it is declared public,
(4.2) an lvalue reference type,
(4.3) a type that contains a placeholder type ([dcl.spec.auto]), or
(4.4) a placeholder for a deduced class type ([dcl.type.class.deduct]).
5: [ Note: Other types are disallowed either explicitly below or implicitly by the rules governing the form of template-arguments ([temp.arg]). — end note ] The top-level cv-qualifiers on the template-parameter are ignored when determining its type.
在 C++17 中,可以在 [temp.param]/4:
中找到限制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
, or- a type that contains a placeholder type.
对 [temp.arg.nontype]/2 中的参数有额外限制:
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.
您出错的地方是 std::plus<int>
不是有效的非类型模板参数。它是第一个列表中那些东西的 none。
在C++20中,可用作非类型模板参数的类型种类将大大扩展。我们将能够使用 class 类型作为非类型模板参数,前提是那些 class 类型满足称为 "strong structural equality." 的东西,在当前草案中,这是根据 [=36= 定义的],默认operator<=>
。在 P1185 中,目前正在开发中,可能会被采用,它会略有变化,以 public 的形式定义,默认为 operator==
.
但即使在 C++20 中,std::plus<int>
实际上也没有定义任何比较运算符 - 因此您仍然无法将其用作非类型模板参数。