You need to enable JavaScript to run this app. C++ 如何为vectors_predicate_view类实现可选的谓词模板参数
优惠活动
大模型
产品
解决方案
定价
更多

C++ 如何为vectors_predicate_view类实现可选的谓词模板参数

vectors_predicate_view类适配可选谓词参数的实现方案

核心调整思路

  • 为第二个模板参数Pred设置默认占位标记类型,标识「用户未显式传入谓词」的场景
  • 用编译期分支逻辑区分两种构造行为:无谓词时直接返回不修改向量,有谓词时执行原有拆分逻辑,无运行时额外开销
  • 对用户传入的谓词做编译期合法性校验,符合现有谓词继承std::unary_function的适配要求

具体实现代码

首先定义占位标记类型,再实现类模板:

#include <vector>
#include <utility>
#include <functional> // 包含std::unary_function定义
#include <type_traits> // 包含类型判断工具

// 占位标记:用户未显式传入谓词时的默认模板参数
struct NoPredicate {};

template <class T, class Pred = NoPredicate>
class vectors_predicate_view {
public:
    vectors_predicate_view(std::vector<T>& vec_a, std::vector<T>& vec_b) {
        // 编译期判断当前是否为无谓词场景
        if constexpr (std::is_same_v<Pred, NoPredicate>) {
            // 不执行任何操作,保留两个向量的原有内容
            return;
        } else {
            // 校验传入谓词是否符合兼容要求
            static_assert(
                std::is_base_of_v<std::unary_function<T, bool>, Pred>,
                "传入的谓词需继承自std::unary_function<T, bool>"
            );

            // 原有拆分逻辑:暂存所有元素后清空原向量
            std::vector<T> temp_storage;
            temp_storage.reserve(vec_a.size() + vec_b.size());
            // 转移原向量元素到暂存区,避免冗余拷贝
            std::move(vec_a.begin(), vec_a.end(), std::back_inserter(temp_storage));
            std::move(vec_b.begin(), vec_b.end(), std::back_inserter(temp_storage));
            vec_a.clear();
            vec_b.clear();

            // 按谓词筛选元素,分别放回两个向量
            Pred pred{};
            for (auto& elem : temp_storage) {
                if (pred(elem)) {
                    vec_a.push_back(std::move(elem));
                } else {
                    vec_b.push_back(std::move(elem));
                }
            }
        }
    }
};

若需兼容不继承std::unary_function的普通可调用类型,可将static_assert中的校验条件替换为std::is_invocable_r_v<bool, Pred, T>,支持任意接收T类型参数返回bool的可调用对象。

使用示例

无谓词场景(不修改原向量)

std::vector<int> a{1, 2, 3}, b{4, 5, 6};
// 不传入第二个模板参数,自动使用默认的NoPredicate
vectors_predicate_view<int> no_op_view(a, b);
// 执行后a、b内容保持不变

有谓词场景(执行拆分逻辑)

// 定义符合要求的谓词(继承自std::unary_function)
struct is_even : std::unary_function<int, bool> {
    bool operator()(int x) const { return x % 2 == 0; }
};

std::vector<int> a{1, 2, 3}, b{4, 5, 6};
// 显式传入谓词模板参数
vectors_predicate_view<int, is_even> split_view(a, b);
// 执行后a存储所有偶数:2,4,6;b存储所有奇数:1,3,5

兼容旧标准的替代方案

若需使用C++17之前的标准(不支持if constexpr),可通过类模板特化为Pred=NoPredicate的场景单独提供空实现版本:

// 通用版本(传入谓词的场景)
template <class T, class Pred = NoPredicate>
class vectors_predicate_view {
    // 此处为上述带拆分逻辑的实现
};

// 特化版本(无谓词的场景)
template <class T>
class vectors_predicate_view<T, NoPredicate> {
public:
    vectors_predicate_view(std::vector<T>&, std::vector<T>&) {
        // 空实现,不修改向量
    }
};

内容的提问来源于stack exchange,提问作者Martin Serdült

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.12 21:45:08