【问题标题】:Lambda copy assignment operator is not defined未定义 Lambda 复制赋值运算符
【发布时间】:2019-06-01 15:15:44
【问题描述】:

为什么这不能用 CLang 7 及更低版本编译,但用 CLang 8 及更高版本编译:

#include <map>
#include <string>

typedef std::map<std::string, int> TestMap;

TestMap m {
    {"a", 1},
    {"b", 2},
    {"c", 3},
};

auto func = [](const TestMap::value_type & p) -> int { return p.second; };
auto func1 = func;
//In CLang 7 and lower copy assignment operator is not defined
func = func1;

实际发生了什么变化?

但这适用于所有 CLang 版本:

auto func1 = []() { return 5;};
decltype(func1) func2 = func1;
func2 = func1;

所有可用的示例代码here

lambda 之间有什么区别?

【问题讨论】:

  • 好问题。您可能希望将代码包装在一个函数中,以便其他人更容易重现您的结果(func2 = func1 不是全局范围内的有效表达式)
  • 从 C++20 see reference 开始可以复制无状态 lambda。现在输入clang status 并检查c++2a 的状态。 8 版本中的 Clang 支持可分配的无状态 lambda。寻找这篇 Default constructible and assignable stateless lambdas 论文。您附加了启用 c++2a 模式的代码链接。
  • 也不用 clang 8 编译。 godbolt.org/z/r5csI3
  • @user10933809 您需要添加-std=c++2a 作为编译器参数。

标签: c++ clang c++17


【解决方案1】:

正如 @rafix07 在 cmets 中提到的,您必须使用 C++20 标准进行编译。

C++20 之前的标准:

ClosureType& operator=(const ClosureType&) = delete; (until C++20)

如果未指定捕获,则闭包类型具有默认副本 赋值运算符和默认的移动赋值 操作员。否则,它有一个已删除的复制赋值运算符(此 包括有默认捕获的情况,即使它没有 实际上捕获任何东西)。 (C++20 起)

复制赋值运算符被定义为删除(和移动 未声明赋值运算符)。闭包类型不是 可复制。 (直到 C++20) ClosureType::operator=(const ClosureType&)

ClosureType& operator=(const ClosureType&) = delete; (until C++20)

ClosureType& operator=(const ClosureType&) = default; (since C++20) 
ClosureType& operator=(ClosureType&&) = default; (only if no captures are specified)

ClosureType& operator=(const ClosureType&) = delete; (since C++20) 
(otherwise) 

https://en.cppreference.com/w/cpp/language/lambda

在此处查看编译:https://godbolt.org/z/jpCYNQ

取自 cmets 中 @Alexey Starinsky 链接的代码示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 2013-12-04
    • 2020-02-28
    • 2020-04-09
    相关资源
    最近更新 更多