繁体   English   中英

C++ 17 元编程递归结构:enum 或 constexpr

[英]C++ 17 Metaprogramming recursive struct: enum or constexpr

为了便于说明,我展示了两个小的、略有不同的模板化递归定义。 一个使用enum ,另一个使用static constexpr来定义一个值。

我检查了两个程序中的 output 程序集,它们完全相同,而且在语义上它们也看起来相同。

我认为constexpr可能更现代一些,但是使用enum / static constexpr之间是否存在任何差异,或者是否存在差异真正重要的任何特定用例?

// using enum
template<uint64_t N>
struct Sum {
    enum : uint64_t { value = N + Sum<N - 1>::value };
};

template<>
struct Sum<0> {
    enum : uint64_t { value = 1 };
};
// using static constexpr
template<uint64_t N>
struct Sum {
    static constexpr uint64_t value = N + Sum<N - 1>::value;
};

template<>
struct Sum<0> {
    static constexpr uint64_t value = 1;
};

提取价值:

#define sum(n) (Sum<n>::value)

最显着的区别(因为 C++17 避免了对 static 数据成员进行类外定义的需要)是枚举数与包含的 class一起实例化,而 static 数据成员仅在需要时实例化。 (但是请注意,至少 MSVC 并不总是正确地延迟它们。)

当您有多个这样的常量并且其中一些仅对某些专业化有意义时,这很重要。 在 static 数据成员案例中实例化 class 不会触发像T::maybe_exists这样的初始化器中的错误

另一个区别:关于ODR-used .

正如@Igor Tandetnik 所说,当您使用&Sum<0>::value时,它仅在valuestatic constexpr变量时才有效。 那是因为, value是枚举数的文字,而不是变量。 但请注意, &valueODR-used ,它要求value在某处只有一个定义。 所以你必须声明uint64_t const Sum<0>::value; XXX.cpp提供定义,在 C++17 之前( static constexpr变量在 C++17 之后隐式是一个inline变量,一个inline变量在翻译单元中允许有多个定义)。

也许您认为“我根本不会使用&value ”。 但在另一种情况下你会遇到麻烦: uint64_t const& a = value ,它也是ODR-used 对于枚举器,其生命周期将通过引用延长(作为引用初始化)。 但是static constexpr变量不会并且需要定义,就像使用&value一样。 当您使用一些 function 通过引用传递时,它总是会造成一些麻烦,例如std::find

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM