我应该内联命名空间范围 lambdas 吗?在任何一种情况下,为什么?

Should I inline namespace scope lambdas? In either case, why?

有时我在头文件的顶部定义了一些无捕获的 lambda,用于头文件的以下部分:

//#include statements
namespace detail {
auto constexpr lambda = [](/* args */){ /* body */ };
}
// in some function or whatever, use `lambda`

我经常在代码审查期间被告知,我不仅应该像我一样放置 constexpr 说明符,还应该放置 inline 说明符。

我为什么要这样做?有什么优势?

我试过阅读 inline specifier on cppreference,但我认为我目前缺乏太多术语来理解它。

如果变量是在头文件中定义的,您应该使用 inline。如果它不是内联的,那么包含头文件的每个翻译单元都将获得该定义。这意味着您对单个名称有多个定义,这是 ODR (One Definition Rule) 违规行为。这些不需要任何诊断,因此它们会导致难以发现错误。

通过使变量内联,您可以通过告诉 compiler/linker 它可以丢弃所有重复的定义并只使用一个定义来解决问题。

根据 C++ 17 标准(10.1.5 constexpr 说明符)

1 The constexpr specifier shall be applied only to the definition of a variable or variable template or the declaration of a function or function template. A function or static data member declared with the constexpr specifier is implicitly an inline function or variable (10.1.6). If any declaration of a function or function template has a constexpr specifier, then all its declarations shall contain the constexpr specifier.

在您问题的代码片段中,变量 lambda 不是静态数据成员。

namespace detail {
auto constexpr lambda = [](/* args */){ /* body */ };
}

因此,如果命名空间 detail 具有外部链接,那么变量 lambda 也具有外部链接。在这种情况下,如果 header 将包含在多个编译单元中,那么一个定义规则将被打破。为避免这种情况,您应该将变量声明为内联变量。