C++20中含非constexpr析构行为类的constexpr实例合法性问询
关于C++20中constexpr析构函数调用
explicit_bzero的合法性问题 先给出你提供的最小可运行示例代码:
#include <type_traits> #include <string.h> struct secret { int value_; constexpr secret(int value) : value_(value) {} constexpr ~secret() { if (!std::is_constant_evaluated()) explicit_bzero(&value_, sizeof(value_)); } }; constexpr secret my_secret = 5; secret my_destroyed_secret = 6;
问题解答
1. 在constexpr析构函数中调用explicit_bzero这类函数是否合法?
合法,但有核心前提:在常量求值过程中,调用explicit_bzero的代码分支不会被执行。
2. 合法的原因是什么?
C++20对constexpr函数的要求是:函数必须能在常量求值环境下完成执行,但不要求函数内所有代码分支都能适配常量环境。
这里std::is_constant_evaluated()在常量求值时返回true,因此!std::is_constant_evaluated()的分支不会进入,也就不会触发explicit_bzero(该函数本身不是constexpr,无法在常量环境运行)。而在运行时求值场景下,这个分支会正常执行,此时已经脱离了常量求值的约束,完全符合标准。
编译器会验证常量求值路径上的代码是否符合constexpr要求,只要std::is_constant_evaluated()的分支判断能准确隔离运行时代码与常量求值代码,这种写法就是合规的。
3. 若不合法,是否有其他实现方式?
既然上述写法合法,它本身就是满足需求的可行方案。如果想要更直观的实现,也可以用模板特化+标签分派的方式区分常量构造与运行时构造:
#include <type_traits> #include <string.h> template<bool IsConstexpr> struct secret_impl { int value_; constexpr secret_impl(int value) : value_(value) {} ~secret_impl() { if constexpr (!IsConstexpr) { explicit_bzero(&value_, sizeof(value_)); } } }; // 运行时构造的版本 using secret = secret_impl<false>; // 常量构造的版本 template<int V> constexpr auto make_constexpr_secret() { return secret_impl<true>{V}; } constexpr auto my_secret = make_constexpr_secret<5>(); secret my_destroyed_secret = 6;
这种写法用if constexpr明确隔离两个分支,常量构造的特化版本析构函数不含擦除逻辑,运行时版本则会执行擦除,同样能满足需求,可读性也更强。
内容的提问来源于stack exchange,提问作者user3188445
相关产品推荐
相关产品推荐

