为什么C++中的拉姆达从来没有缺省构造

问题描述:

我有lambda表达式没有捕获任何,

为什么C++中的拉姆达从来没有缺省构造

[](){}; 

我有一个模板类,它包含这样的拉姆达。由于lambda不包含非静态数据成员,也不包含虚函数,因此它应该是一个空类和DefaultConstructible。它只是一种可用于模板元编程的策略类。我想知道,为什么这样的类不是C++标准默认构造的。

旁注:Understanding how Lambda closure type has deleted default constructor提出了一个不同的问题,虽然标题似乎非常相似。它问如何在没有可用的默认构造函数的情况下创建一个无状态的lambda对象。我在问为什么没有可用的默认构造函数。

+2

[This question](http:// *。com/questions/32911729/understanding-how-lambda-closure-type-has-deleted-default-constructor)可能是相关的。 –

+0

你会如何默认构建一个lambda? '[] {}'已经构造出一个并给你实例。 – rustyx

+0

@rustyx像这样:'auto f =()[] {};使用f_t = decltype(f); f_t {};' - 这有效,但是因为lambda已经删除了默认的构造函数。 –

Lambdas旨在创建然后使用。标准因此说“不,他们没有默认的构造函数”。唯一的办法是通过一个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(*)()[](){}constexpr在C++ 17,function_pointer_t<+[](){}>是一个什么都不做的函数对象那就是DefaultConstructible。

这实际上并不包含lambda,而是lambda产生的指针函数。

+1

'''function_pointer_t '中的'+'是故意的,如果是这样的话,意味着什么? –

+3

@ PeterA.Schneider它[将空捕获组的lambdas转换为函数指针。](http://*.com/questions/18889028/a-positive-lambda-what-sorcery-is-this) – jaggedSpire

+0

好吧,我试过了你的解决方案但是我有了C++ 17可用,它不起作用。首先它偶然发现'template ',我可以通过使用'void(*)()'类型来解决这个问题。然而,编译器抱怨'function_pointer_t '在模板参数(GCC)中使用lambda表达式,或者lambda表达式可能不出现在常量表达式(Clang)中。这是由于GCC 6.1和Clang 3.8关于C++ 17的不完整性,还是Yakk的答案不符合C++ 17标准? –

我假设你熟悉类型,对象和表达式之间的区别。在C++中,λλ具体指的是λ表达式。这是一个方便的方式来表示一个非平凡的对象。但是,它很方便:您可以通过编写代码自己创建一个类似的对象。

现在,根据C++规则,每个表达式都有一个类型,但该类型不是lambda表达式的目的。这就是为什么它是一个未命名和独特的类型--C++委员会认为不值得定义这些属性。同样,如果它被定义为具有默认ctor,则标准应定义该行为。根据目前的规则,不需要定义默认ctor的行为。

正如你所注意到的,对于[](){}的特殊情况,定义一个默认ctor是很简单的。但这没有意义。你马上就会遇到第一个难题:为什么lambda应该定义默认的ctor?什么lambda的子集足够简单,有一个体面的定义,但足够复杂,有趣?没有一致意见,你不能期望这是标准化的。

请注意,作为扩展的编译器供应商已经可以提供此功能。标准化通常遵循现有的做法,参见Boost。但是,如果没有编译器供应商个人认为这是值得的,他们为什么一致认为这么做?

+0

实际上,您可以将lambda看作是一个对象,它是由将捕获列表作为构造函数参数的构造函数创建的。具有空捕获列表的lambda自然应该有一个默认的构造函数恕我直言。 –