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

如何编写可被编译器适配的C++ Contracts?宏与编译选项疑问

C++ Contracts 编写与兼容指南

一、标准合规的Contracts编写方式

C++20标准中,Contracts通过带参数的属性实现,正确语法如下:

  • 前置条件(expects):约束函数调用前必须满足的条件,放在函数参数列表之后、函数体之前
  • 后置条件(ensures):约束函数返回时必须满足的条件,位置与expects一致

示例代码:

// 前置条件:传入指针不能为空
void process(X* x) [[expects: x != nullptr]] {
    // 函数逻辑
}

// 后置条件:返回时x的u成员必须大于0
int calculate(X* x) [[ensures: x->u > 0]] {
    x->u = 42;
    return x->u;
}

注意:你提到的float f(X *x)[[expects:x]]属于旧草案写法,已被标准废弃,需使用上述标准语法。

二、无Contracts支持的编译器兼容方案

直接写[[expects:...]]或[[ensures:...]]会在不支持的编译器上触发语法错误——旧编译器不支持带参数的属性语法,无法像普通未知属性那样忽略。因此必须通过条件编译宏包装Contracts代码,让无支持的编译器自动跳过。

推荐的宏包装实现

无需手动定义USE_CONTRACTS,直接利用编译器的特性检测宏自动判断:

// 检测标准C++20 Contracts支持
#if defined(__cpp_contracts)
#define EXPECTS(cond) [[expects: cond]]
#define ENSURES(cond) [[ensures: cond]]
// GCC实验性支持(需加-fcontracts编译选项)
#elif defined(__GCC_CONTRACTS)
#define EXPECTS(cond) [[expects: cond]]
#define ENSURES(cond) [[ensures: cond]]
// Clang实验性支持(需加-fcxx-contracts编译选项)
#elif defined(__clang_contracts)
#define EXPECTS(cond) [[expects: cond]]
#define ENSURES(cond) [[ensures: cond]]
// 无支持时,宏展开为空
#else
#define EXPECTS(cond)
#define ENSURES(cond)
#endif

// 实际使用
void process(X* x) EXPECTS(x != nullptr) {
    // ...
}

int calculate(X* x) ENSURES(x->u > 0) {
    // ...
}

三、特性检测宏说明

存在无需手动传入编译选项的自动特性检测宏:

  • __cpp_contracts:C标准规定的特性检测宏,编译器支持C20 Contracts时会自动定义(值为对应标准版本号,如201907L)
  • 编译器扩展宏:
    • GCC:__GCC_CONTRACTS,需开启编译选项-fcontracts才会定义
    • Clang:__clang_contracts,需开启编译选项-fcxx-contracts才会定义

注意:即使编译器支持C++20,默认可能不启用Contracts检查,仍需手动添加编译选项激活,但宏的检测是自动的,无需用户额外定义USE_CONTRACTS。

四、关键注意事项

  • 不要直接使用带参数的Contracts属性,必须用宏包装,否则旧编译器会报语法错误
  • 不同编译器的Contracts编译选项不同,需根据目标编译器调整(如GCC用-fcontracts,Clang用-fcxx-contracts)
  • 目前主流编译器对C++20 Contracts的支持仍处于实验阶段,部分特性可能未完全实现

内容的提问来源于stack exchange,提问作者A Pacific Spammer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:30:12