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

C++20以函数类型为参数的Concept:如何简洁实现并遵循DRY原则

优化泛型二元操作的Concept实现

核心思路是把操作逻辑和类型约束解耦:让Concept只负责判断类型是否支持"分发操作到成员"的能力,具体操作逻辑只在函数内部实现一次,不再重复写到Concept约束里。

步骤1:定义只关注类型能力的Concept

不再让Concept依赖具体的操作函数,而是检查类型是否提供统一的成员访问接口(比如apply方法),或者通过SFINAE判断能否对其成员应用二元操作:

#include <concepts>
#include <utility>
#include <tuple>

// 定义Distributive Concept:判断类型T是否支持二元操作分发
template<typename T>
concept Distributive = requires(T a, T b, double (*op)(double, double)) {
    { a.apply(op, b) } -> std::same_as<T>;
};

// 基础类型double直接适配Concept
template<>
concept Distributive<double> = true;

步骤2:实现统一的分发工具函数

把原来重复的Lambda逻辑封装到distribute函数中,操作逻辑只写一次:

// 基础类型的分发:直接调用操作符
double distribute(double a, double b, auto op) {
    return op(a, b);
}

// 针对Distributive类型的分发:调用类型自身的apply方法
template<Distributive T>
T distribute(T a, T b, auto op) {
    return a.apply(op, b);
}

// 示例聚合类型foo:实现apply方法处理成员
template<typename... Args>
struct foo {
    std::tuple<Args...> members;

    template<typename Op>
    foo apply(Op op, const foo& other) const {
        return {std::apply([&](auto&&... args) {
            return std::make_tuple(op(args, std::get<decltype(args)>(other.members))...);
        }, members)};
    }
};

// 嵌套类型bar:递归调用apply处理内部成员
struct bar {
    foo<double, double> inner;

    template<typename Op>
    bar apply(Op op, const bar& other) const {
        return {inner.apply(op, other.inner)};
    }
};

步骤3:简洁的binop实现

现在binop的约束只需要用Distributive,不需要重复Lambda逻辑,直接用Distributive auto即可:

// 泛型二元操作,约束简洁明了
auto binop(Distributive auto a, Distributive auto b, auto op) {
    return distribute(a, b, op);
}

// 使用示例
int main() {
    double d1 = 1.0, d2 = 2.0;
    auto d_res = binop(d1, d2, [](double x, double y) { return x + y; });

    foo<double> f1{{3.0}}, f2{{4.0}};
    auto f_res = binop(f1, f2, [](double x, double y) { return x * y; });

    bar b1{{{5.0, 6.0}}}, b2{{{7.0, 8.0}}};
    auto b_res = binop(b1, b2, [](double x, double y) { return x - y; });
}

关键优化点

  1. 解耦类型约束与操作逻辑:Concept只关注类型是否具备分发能力,不绑定具体操作,彻底避免Lambda重复。
  2. 统一分发入口:通过distribute函数集中处理不同类型的操作分发,逻辑只维护一次。
  3. 语法简洁性:直接使用Distributive auto,完全符合你期望的简洁写法。

内容的提问来源于stack exchange,提问作者Involute

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:57:19