c++20 Concepts的简写形式与requires 从句形式

发布于:2025-03-14 ⋅ 阅读:(22) ⋅ 点赞:(0)

在 C++20 Concepts 中,使用简写形式的 template<ConceptName T> 与使用完整形式的 template<typename T> requires ConceptName<T> 是等价的。以下是两种写法的具体转换:

原始写法(简写形式)

template<typename T>
concept Arithmetic = std::is_arithmetic_v<T>;

template<Arithmetic T>  // 简写形式
T add(T a, T b) { return a + b; }

等效写法(requires 从句形式)

template<typename T>
concept Arithmetic = std::is_arithmetic_v<T>;

template<typename T>    // 完整形式
requires Arithmetic<T>  // requires 从句
T add(T a, T b) { return a + b; }

关键区别说明:

特征 简写形式 requires 从句形式
语法结构 template<ConceptName T> template<typename T> requires ...
可组合性 只能指定单个 Concept 可通过逻辑运算符组合多个约束
约束表达式位置 模板参数声明中 模板参数列表后的 requires 从句中
适用场景 简单约束 复杂约束(需要组合多个条件时)

组合多个约束的示例:

template<typename T>
concept Signed = std::is_signed_v<T>;

template<typename T>
requires Arithmetic<T> && Signed<T>  // 组合两个约束
T negative(T value) {
    return -value;
}

negative(5);     // OK
negative(3.14);  // OK
negative("123"); // 错误:不满足 Arithmetic 约束
negative(2u);    // 错误:unsigned 不满足 Signed 约束

两种形式的编译结果:

  1. 错误信息对比

    add("hello", "world");  // 错误信息中会明确显示:
    // 简写形式:"constraints not satisfied for 'T'"
    // requires 从句形式:"constraint 'Arithmetic<T>' was not satisfied"
    
  2. 元编程特性保留

    template<Arithmetic T>      // 两种形式均可配合
    struct Calculator {         // SFINAE、if constexpr 等特性
        static_assert(Signed<T>);
    };
    

更复杂的约束示例:

template<typename T>
concept Printable = requires(std::ostream& os, T val) {
    { os << val } -> std::same_as<std::ostream&>;
};

template<typename T>
requires Arithmetic<T> && Printable<T>
void print_sum(T a, T b) {
    std::cout << (a + b) << "\n";
}

print_sum(3, 5);    // OK:int 是算术类型且可打印
print_sum(2.71, 3); // OK:double 符合条件
print_sum(true, false); // 错误:bool 是算术类型但不符合 Printable(需要重载<<)

标准库风格的约束:

template<typename T>
concept Addable = requires(T a, T b) {
    { a + b } -> std::convertible_to<T>;
};

template<typename T>
requires Addable<T>  // 替代 C++17 的 std::void_t 技巧
T sum(T a, T b) { return a + b; }

建议:当约束条件简单时使用简写形式,需要组合多个约束或需要更清晰的错误信息时使用 requires 从句形式。


网站公告

今日签到

点亮在社区的每一天
去签到