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

如何避免传递重复依赖类型?优化TopNStorage模板参数写法

实现TopNStorage类的谓词模板参数自动推导,避免类型冗余

当前实现的TopNStorage类模板需要手动指定谓词的具体实例化类型(如std::less<int>),其中int与类模板的T类型重复,希望优化为仅传入谓词模板(如std::less),让编译器自动从T推导谓词的类型参数,使客户端代码可以写成:

TopNStorage<int, std::less> storage(3);

原实现代码

#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>

template <typename T, typename Pred = std::greater<T>>
class TopNStorage {
    std::priority_queue<T, std::vector<T>, Pred> counts;
    size_t n;
public: 
    TopNStorage(size_t n) : n(n) {  }

    void add(T value) {
        if (counts.size() >= n) {
            if (Pred()(value, counts.top())) {
                counts.pop();
                counts.push(value);
            }
        }
        else {
            counts.push(value);
        }
    }

    auto get_values() const { 
        std::vector<T> sorted_collocations_counts(counts.size());

        std::copy(&(counts.top()), &(counts.top()) + counts.size(), sorted_collocations_counts.begin());
        std::sort(sorted_collocations_counts.begin(), sorted_collocations_counts.end(),Compare());

        return sorted_collocations_counts;
    }
};

int main() {
    TopNStorage<int,std::less<int>> storage(3);

    for (int i = 1; i <= 5; ++i) {
        storage.add(i);
    }

    for (auto value : storage.get_values()) {
        std::cout << value << "\n";
    }
} 

解决方案:使用模板模板参数

通过将类模板的第二个参数改为模板模板参数,可以实现谓词类型的自动推导,避免重复指定T类型。

修改后的完整代码

#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <functional> // 用于std::not_fn

// 将第二个参数改为模板模板参数,默认使用std::greater
template <typename T, template <typename> typename Pred = std::greater>
class TopNStorage {
    // 用T实例化Pred模板,得到具体的谓词类型
    using PredType = Pred<T>;
    std::priority_queue<T, std::vector<T>, PredType> counts;
    size_t n;
public: 
    TopNStorage(size_t n) : n(n) {  }

    void add(T value) {
        if (counts.size() >= n) {
            // 实例化PredType对象进行比较
            if (PredType()(value, counts.top())) {
                counts.pop();
                counts.push(value);
            }
        }
        else {
            counts.push(value);
        }
    }

    auto get_values() const { 
        std::vector<T> result(counts.size());
        // 修复拷贝逻辑:priority_queue的底层元素不按堆序连续排列,需通过临时队列遍历
        auto temp_queue = counts;
        size_t idx = 0;
        while (!temp_queue.empty()) {
            result[idx++] = temp_queue.top();
            temp_queue.pop();
        }
        // 反转谓词排序,让输出结果符合直观的顺序
        std::sort(result.begin(), result.end(), std::not_fn(PredType()));
        return result;
    }
};

int main() {
    // 仅传入std::less模板,无需指定<int>
    TopNStorage<int, std::less> storage(3);

    for (int i = 1; i <= 5; ++i) {
        storage.add(i);
    }

    for (auto value : storage.get_values()) {
        std::cout << value << "\n";
    }
} 

关键修改点说明

  1. 模板参数调整:将原有的typename Pred改为template <typename> typename Pred,允许传入一个模板(如std::less、std::greater)而非实例化后的类型。
  2. 谓词自动实例化:在类内部通过using PredType = Pred<T>,用类模板的T自动推导并实例化谓词模板,彻底消除类型冗余。
  3. 修复拷贝逻辑:原代码直接通过&counts.top()拷贝的方式错误,因为std::priority_queue的底层容器元素并非按堆序排列,改为通过临时队列遍历拷贝,保证元素完整取出。
  4. 排序逻辑优化:使用std::not_fn反转谓词,让输出结果的排序符合直观预期(例如用std::less时,队列存最大的N个元素,反转后输出升序结果)。

效果验证

修改后的客户端代码只需写TopNStorage<int, std::less>,无需重复指定int,既减少了代码冗余,也避免了因类型不同步导致的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:12:41