我有没有抓住任何东西的lambdas,比如
[](){};
我有一个包含这样一个lambda的模板类。由于lambda不包含非静态数据成员,也不包含虚函数,因此它应该是一个空类和DefaultConstructible。它只是一种可用于模板元编程的策略类。我想知道,为什么这样的类不是C ++标准的默认构造。
旁注: Understanding how Lambda closure type has deleted default constructor提出了一个不同的问题,虽然标题似乎非常相似。它询问如何在没有可用的默认构造函数的情况下创建无状态lambda对象。我问为什么没有可用的默认构造函数。
答案 0 :(得分:8)
Lambda用于创建然后使用。因此标准说'不,他们没有默认的构造函数"。制作一个的唯一方法是通过lambda表达式或其副本。
他们不打算将他们的类型作为你保留和使用的东西。这样做可能会导致ODR违规,并且要求编译器避免ODR违规会使符号损失过于复杂。
但是,在C ++ 17中,您可以围绕函数指针编写无状态包装器:
template<auto fptr>
struct function_pointer_t {
template<class...Args>
// or decltype(auto):
std::result_of_t< std::decay_t<decltype(fptr)>(Args...) >
operator()(Args&&...args)const
return fptr(std::forward<Args>(args)...);
}
};
由于operator void(*)()
上的[](){}
在C ++ 17中为constexpr
,function_pointer_t<+[](){}>
是一个无操作的函数对象,它是DefaultConstructible。
这实际上并没有包裹lambda,而是lambda生成的指向函数的指针。
答案 1 :(得分:2)
我假设您熟悉类型,对象和表达式之间的区别。在C ++中, lambda 特指一个 lambda表达式。这是表示非平凡的对象的便捷方式。但是,它很方便:你可以通过写出代码来自己创建一个类似的对象。
现在根据C ++规则,每个表达式都有一个类型,但该类型不是lambda表达式的用途。这就是为什么它是一个未命名和独特的类型--C ++委员会认为定义这些属性是不值得的。类似地,如果它被定义为具有默认ctor,则标准应该定义行为。使用当前规则,无需定义默认ctor的行为。
正如您所注意到的,对于[](){}
的特殊情况,定义默认ctor是微不足道的。但这没有意义。你立刻得到了第一个难题:为什么lambda应该定义默认的ctor? lambda的哪个子集很简单,有一个不错的定义,但复杂到足以引起兴趣?如果没有达成共识,你不能指望这是标准化的。
请注意,编译器供应商作为扩展已经可以提供此功能。标准化通常遵循现有的做法,参见Boost。但是如果没有编译器供应商认为它是值得的,他们为什么会这样认为是一致的呢?
答案 2 :(得分:0)
在 C++20 中,无状态 lambda 是默认可构造的。所以,现在这种操作是有效的:
auto func = []{};
decltype(func) another_func;