可以将包含函数指针的类用作非类型模板参数吗? [英] Can a class containing a function pointer be used as a non-type template parameter?
问题描述
考虑以下包含函数指针的类 S
和该类的以lambda初始化的 constexpr
对象 s
:
Consider the following class S
containing a function pointer, and a constexpr
object s
of that class initialized with a lambda:
struct S
{
void (*f) ();
};
constexpr S s { []{} };
现在,如果我编写一个类型为 S
的非类型模板参数的模板 X
,并通过 s
实例化它,如下所示:
Now if I write a template X
with a non-type template parameter of type S
, and instantiate it over s
like this:
template<S> struct X {};
using x = X<s>;
clang编译代码,但是gcc抱怨:
clang compiles the code, but gcc complains with:
error: '<lambda()>::_FUN' is not a valid template argument of type 'void (*)()' because '<lambda()>::_FUN' is not a variable
using x = X<s>;
^
这是程序.
代码对我来说似乎很好,而且我不确定错误消息指的是什么.这段代码有效吗?
The code seems fine to me, and I'm not sure what the error message is referring to. So is this code valid?
请注意,如果 X
具有引用类型为 S
的非类型模板参数,则两个编译器均接受该代码,如下所示:
Note that both compilers accept the code if X
instead has a non-type template parameter of reference type to S
, like this:
template<S const &> struct X {};
这个问题的灵感来自另一个类似的问题.
推荐答案
该代码有效.
非类型 template-parameter 的 template-argument 应该是类型的转换后的常量表达式([expr.const]).模板参数.
类型为
T
的转换后的常量表达式是一个隐式转换为类型T
的表达式,其中转换后的表达式为常量表达式,隐式转换序列仅包含[...]
A converted constant expression of type
T
is an expression, implicitly converted to typeT
, where the converted expression is a constant expression and the implicit conversion sequence contains only [...]
(在这种情况下,没有隐式转换.)
(There's no implicit conversion in this case.)
一个常量表达式是[...]或一个prvalue核心常量表达式,其值满足以下约束:
A constant expression is [...] or a prvalue core constant expression whose value satisfies the following constraints:
- 如果该值是类类型的对象,则每个引用类型的非静态数据成员都引用一个实体,该实体是常量表达式的允许结果,
- 如果该值是指针类型,则它包含[...]非立即函数的地址[...],
- 如果该值是指向成员函数类型的指针,[...],
- 如果值是类或数组类型的对象,则每个子对象都满足该值的这些约束.
如果[...]或它是非立即函数,则实体是常量表达式的允许结果.
An entity is a permitted result of a constant expression if [...] or if it is a non-immediate function.
(除了 consteval
功能之外,所有功能都不是直接的.
(All functions are non-immediate except for the consteval
ones. [dcl.constexpr])
因此, s
是类型为 S
的有效转换常量表达式.此外,它不受 [temp.arg.nontype]/3的约束(仅适用于对象的指针/引用).
Therefore, s
is a valid converted constant expression of type S
. In addition, it is not subject to [temp.arg.nontype]/3 (which only applies to pointer/reference to objects).
也就是说, s
是有效的模板参数.
That is, s
is a valid template argument.
我不确定错误消息指的是什么
I'm not sure what the error message is referring to
这是胡说八道.
从 <代码在GCC中> invalid_tparm_referent_p .它是从实现类非类型模板参数时处理对象类型指针的代码中提取的( 4be5c72 ).显然,实现者忘记了更新此功能以解决指针指向功能的情况.
The error is emitted from invalid_tparm_referent_p
inside GCC. It was extracted from code for handling pointer to object type when class non-type template paramter was implemented (4be5c72). Apparently, the implementer forgot to update this function to account for the pointer-to-function case.
我将错误报告为 https://gcc.gnu.org/PR97700 .
这篇关于可以将包含函数指针的类用作非类型模板参数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!