Clang14编译C++20默认<=>运算符触发零作为空指针常量报错
问题背景
存在同类型zero as null pointer constant报错的场景为迭代器比较,本问题发生于模板类比较场景。
在将C14代码库迁移至C20标准的过程中,使用三路比较运算符(<=>,又称spaceship operator)时触发zero as null pointer constant报错,无法定位报错触发原因与具体含义。
编译环境
- 编译器:
clang++14 - 编译参数:
-std=c++20 -Werror -Wzero-as-null-pointer-constant
最小可复现代码
#include <compare> template<typename V, typename U> class quantity { public: using value_type = V; using unit_type = U; using this_type = quantity<value_type, unit_type>; constexpr quantity() : value_() {} constexpr quantity( const value_type &v, unit_type ) : value_( v ) {} constexpr auto operator<=> ( const this_type &rhs ) const = default; private: value_type value_; }; class energy_in_joule_tag{}; using energy = quantity<int, energy_in_joule_tag>; int main() { const energy lo = energy(0, energy::unit_type{} ); const energy hi = energy(1000, energy::unit_type{} ); energy out = energy(20, energy::unit_type{} ); if( out < lo || out > hi ) { return 1; } }
完整报错信息
<source>:14:74: error: zero as null pointer constant [-Werror,-Wzero-as-null-pointer-constant] constexpr auto operator<=> ( const this_type &rhs ) const = default; ^ nullptr <source>:29:13: note: in defaulted three-way comparison operator for 'quantity<int, energy_in_joule_tag>' first required here if( out < lo || out > hi ) { ^ 1 error generated. Compiler returned: 1
报错原因
该问题是Clang 14版本的实现缺陷导致:
Clang 14对C++20默认三路比较运算符的实现不完善,当使用auto作为默认operator<=>的返回类型时,编译器在逐成员生成比较逻辑的过程中,会使用字面量0作为比较类别的空哨兵值构造参数,触发-Wzero-as-null-pointer-constant告警,在-Werror参数下被直接判定为编译错误。
解决方案
可任选以下一种方案修复:
- 显式指定三路比较运算符的返回值类型,避免自动推导触发缺陷:将运算符声明修改为
由于类成员constexpr std::strong_ordering operator<=>( const this_type &rhs ) const = default;value_为int类型,对应的比较类别为std::strong_ordering,显式指定返回类型后编译器不会走有缺陷的自动推导逻辑,即可消除报错。 - 升级Clang版本至15及以上,新版本已经修复了默认三路比较生成逻辑的该告警问题,无需修改代码即可正常编译。
内容的提问来源于stack exchange,提问作者scarf
相关产品推荐
相关产品推荐

