我应该内联命名空间范围 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 将包含在多个编译单元中,那么一个定义规则将被打破。为避免这种情况,您应该将变量声明为内联变量。
有时我在头文件的顶部定义了一些无捕获的 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 将包含在多个编译单元中,那么一个定义规则将被打破。为避免这种情况,您应该将变量声明为内联变量。