c++ - 翻译单元之间共享的 Lambda 变量

标签 c++ lambda c++20

我有一个在头文件中共享的变量。它是用 lambda 初始化的。我希望从另一个翻译单元调用一个函数,并以此 lambda 变量作为参数。

使用 gcc,我收到错误:

used but never defined [-fpermissive].

这是一个简化的示例:

// in shared header file
//
const auto make_lambda() { return [](){ }; }
inline const auto lambda = make_lambda();

// in cpp file
//
void func(const decltype(lambda)&);

int main() {
    func(lambda);
}

我的理解是 lambda 类型应该在翻译单元之间共享。

当我将 lambda 变量更改为以下内容时,问题就消失了:

inline const auto lambda = [](){ }; // <-- this does work

最佳答案

Clang 提供了出色的诊断,可以解释 make_lambda 的问题嗯:

<source>:8:6: error: function 'func' is used but not defined in this translation unit,
                     and cannot be defined in any other translation unit because its type
                     does not have linkage
void func(const decltype(lambda)&);
     ^

“无链接”意味着:

When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.

-[basic.link]/2.4

我们的 lambda 没有链接的原因是它定义的闭包类型是在 make_lambda内部定义的。 。结果是:

Names not covered by these rules have no linkage. Moreover, except as noted, a name declared at block scope has no linkage.

-[basic.link]/7

您尝试使用的类型是 make_lambda::__lambda本质上,这不能跨不同的 TU 使用。

共享 lambda 表达式的 ODR 问题

inline const auto lambda = [](){ };

...使编译器错误消失,但这会使您的程序格式错误,无需诊断。我们必须尊重单一定义规则,但我们违反了以下规定:

In each such definition, except within the default arguments and default template arguments of D, corresponding lambda-expressions shall have the same closure type (see below).

-[basic.def.odr]/14.6

每个 TU 都有自己独特的闭合类型,但是 lambda到处都必须有相同的定义。 这是 ODR 违规行为。

如果你真的坚持这样做,安全的方法是将其放入类类型中:

struct dummy {
    using lambda_type = [] {};
};

dummy::lambda_type将具有链接并且不违反 ODR。 另请参阅:[basic.def.odr]/16

结论

只是不要在不同的 TU 之间共享 lambda。即使你让它工作,解决方案也不是很好。相反,请考虑:

  • 编写一个接受任何可调用内容的函数模板
  • 接受函数指针
  • 接受std::function
  • 创建一个常规类,而不是 lambda,它具有重载的调用运算符

所有这些选项都比尝试在 TU 之间共享 lambda 表达式(在函数之外)要好得多。

关于c++ - 翻译单元之间共享的 Lambda 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76582942/

相关文章:

c++ - 如何将 boost 库添加到 Visual Studio Linux 项目中?

c++ - 读取字符列表并存储在数组中

c++ - 为什么 std::sort 在比较函数使用大于 (>) 而不是大于或等于 (>=) 时起作用?

c++ - 继承函数的重载解决方案

c++ - 如何通过某个元素可以在特定专业范围内进行评估?

C++ 内联 lambda 参数的概念

c++ - 引用已释放的内存是未定义的行为吗?

python - 'lambda variable=variable: somefunction()' 是如何工作的?

c# - 当 .NET 只依赖于参数时,我应该使用委托(delegate)还是方法?

c++ - 为什么 std::accumulate 在 C++20 中没有被设为 constexpr?