You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 17:42:25