标准是否保证 lambda 的可继承性?
Is inheritability of lambdas guaranteed by the standard?
在C++标准中,闭包类型定义如下:
[expr.prim.lambda.closure]
The type of a lambda-expression (which is also the type of the closure
object) is a unique, unnamed non-union class type, called the closure
type, whose properties are described below. [...]
该标准似乎没有定义未命名的非联合 class 类型是否为最终类型。将 lambdas 实现为 final classes 的编译器是否符合标准,或者我们是否可以保证可以从 lambdas 继承?
问题不在于从 lambdas 继承是否有用:它是有用的。问题是标准是否提供这种保证。
是的,闭包类型不能是 final。至少那是我的解释。
§8.1.5.1 Closure types [expr.prim.lambda.closure]
An implementation may define the closure type differently from what is
described below provided this does not alter the observable behavior
of the program other than by changing:
- ... [does not apply]
该标准并未将闭包类型描述为最终的。将其设置为 final 会改变可观察到的行为,因此闭包类型不能是 final。
关于可观察到的行为。考虑一下:
auto l = []{};
return std::is_final_v<decltype(l)>;
将闭包类型设置为 final 显然会修改有效程序的可观察行为。
关于用例,它实际上可以是一个非常有用的功能:
template <class... Fs> struct Overload : Fs ...
{
using Fs::operator()...;
};
template <class... Fs> Overload(Fs...) -> Overload<Fs...>;
auto test()
{
Overload f = {[] (int a) { return a * 100; },
[] (int a, int b) { return a + b;}};
return f(1) + f(2, 3); // 105
}
在 godbolt
上查看实际效果
感谢 hvd 和 rakete1111 在评论中的讨论和反馈。
final
的效果在[class]/3中指定:
If a class is marked with the class-virt-specifier final
and it appears as a class-or-decltype in a base-clause, the program is ill-formed.
也就是说,class 是否是最终的并不重要。只有 class 是否 标记 与 final
说明符才重要。由于闭包类型在源文件中没有任何声明,因此不可能将其标记为 final
,因此 [class]/3 不适用。
在C++标准中,闭包类型定义如下:
[expr.prim.lambda.closure] The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below. [...]
该标准似乎没有定义未命名的非联合 class 类型是否为最终类型。将 lambdas 实现为 final classes 的编译器是否符合标准,或者我们是否可以保证可以从 lambdas 继承?
问题不在于从 lambdas 继承是否有用:它是有用的。问题是标准是否提供这种保证。
是的,闭包类型不能是 final。至少那是我的解释。
§8.1.5.1 Closure types [expr.prim.lambda.closure]
An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:
- ... [does not apply]
该标准并未将闭包类型描述为最终的。将其设置为 final 会改变可观察到的行为,因此闭包类型不能是 final。
关于可观察到的行为。考虑一下:
auto l = []{};
return std::is_final_v<decltype(l)>;
将闭包类型设置为 final 显然会修改有效程序的可观察行为。
关于用例,它实际上可以是一个非常有用的功能:
template <class... Fs> struct Overload : Fs ...
{
using Fs::operator()...;
};
template <class... Fs> Overload(Fs...) -> Overload<Fs...>;
auto test()
{
Overload f = {[] (int a) { return a * 100; },
[] (int a, int b) { return a + b;}};
return f(1) + f(2, 3); // 105
}
在 godbolt
上查看实际效果感谢 hvd 和 rakete1111 在评论中的讨论和反馈。
final
的效果在[class]/3中指定:
If a class is marked with the class-virt-specifier
final
and it appears as a class-or-decltype in a base-clause, the program is ill-formed.
也就是说,class 是否是最终的并不重要。只有 class 是否 标记 与 final
说明符才重要。由于闭包类型在源文件中没有任何声明,因此不可能将其标记为 final
,因此 [class]/3 不适用。