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

能否让算法泛型处理对象成员以计算复合类型的极值?

为复合类型计算成员独立极值的模板实现

问题背景

需要为容器计算极值(最小值和最大值),但容器可能包含未显式定义operator<的复合类型,因此需要将其成员视为PoD类型分别进行比较。

现有PoD类型极值模板

最初实现的模板对float等基础PoD类型工作正常:

#include <limits>

template <typename T>
struct extents {
    // 初始化极值为边界值,便于后续更新
    T min = std::numeric_limits<T>::max(),
      max = std::numeric_limits<T>::lowest();

    void update(T value) {
        min = std::min(min, value);
        max = std::max(max, value);
    }

    T midpoint() const {
        return std::midpoint(min, max);
    }
};

使用示例(PoD类型)

float a[] = { 1.0f, 5.0f, 2.0f, 3.0f };

extents<float> ext;

for (auto v : a) {
    ext.update(v);
}

复合类型的问题

当处理如vec2这类复合类型时,由于未定义operator<,直接使用上述模板会编译失败。且我们的需求是分别比较每个成员的对应值,而非对复合类型进行整体比较,因此不适合定义通用的operator<。

期望实现的调用方式类似std::ranges::sort,通过指定成员指针来让模板自动处理每个成员的极值:

vec2 va[] = { {1.0f, 3.0f}, {5.0f, 2.0f}, {1.0f, 3.0f} };

extents<vec2> vext(&vec2::x, &vec2::y);

for (auto v : va) {
    vext.update(v);
}

解决方案:可变参数模板实现

通过可变参数模板扩展extents,使其支持存储多个成员的独立极值,并在update时自动遍历更新每个成员:

#include <limits>
#include <tuple>
#include <utility>

// 针对单个PoD类型的特化
template <typename T>
struct extents<T> {
    T min = std::numeric_limits<T>::max();
    T max = std::numeric_limits<T>::lowest();

    void update(T value) {
        min = std::min(min, value);
        max = std::max(max, value);
    }

    T midpoint() const {
        return std::midpoint(min, max);
    }
};

// 支持复合类型多成员的模板
template <typename T, typename... Members>
struct extents {
private:
    std::tuple<extents<std::decay_t<decltype(std::declval<T>().*std::declval<Members>())>>...> member_extents;
    std::tuple<Members...> members;

    template <std::size_t... Is>
    void update_impl(const T& value, std::index_sequence<Is...>) {
        (std::get<Is>(member_extents).update(value.*std::get<Is>(members)), ...);
    }

public:
    explicit extents(Members... ms) : members(std::make_tuple(ms...)) {}

    void update(const T& value) {
        update_impl(value, std::index_sequence_for<Members...>{});
    }

    template <std::size_t I>
    auto& get() {
        return std::get<I>(member_extents);
    }

    template <std::size_t I>
    const auto& get() const {
        return std::get<I>(member_extents);
    }
};

使用示例(复合类型)

// 定义复合类型
struct vec2 {
    float x;
    float y;
};

int main() {
    vec2 va[] = { {1.0f, 3.0f}, {5.0f, 2.0f}, {1.0f, 3.0f} };
    extents<vec2, decltype(&vec2::x), decltype(&vec2::y)> vext(&vec2::x, &vec2::y);

    for (auto v : va) {
        vext.update(v);
    }

    // 获取x成员的极值
    float x_min = vext.get<0>().min; // 1.0f
    float x_max = vext.get<0>().max; // 5.0f

    // 获取y成员的极值
    float y_min = vext.get<1>().min; // 2.0f
    float y_max = vext.get<1>().max; // 3.0f
}

方案优势

  • 支持任意数量的成员,适配不同结构的复合类型
  • 每个成员独立维护极值,完全符合“分别比较对应成员”的需求
  • 保留原PoD类型的使用方式,兼容性强
  • 调用逻辑与std::ranges::sort一致,学习成本低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 19:54:50