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

C++泛型filter函数适配任意容器任意类型的实现问题求助

解决C++ filter函数支持任意容器的模板错误问题

问题背景

需要实现一个通用的filter函数,要求:

  • 初始版本支持std::list和std::function谓词,返回满足条件的新列表
  • 改进1:支持任意元素类型的std::list(已完成)
  • 改进2:支持任意类型的容器(实现时遇到编译错误)

初始改进后的可运行代码:

#include <iostream>
#include <list>
#include <functional>

template <typename T>
std::list<T> filter (std::list<T>& l, std::function<bool(T)> p){
  for (auto it = l.begin(); it != l.end(); ++it){
    if (p(*it)){
      continue;
    }
    else {
      it = l.erase(it);
    }
  }
  return l;
}

int main()
{
  std::list<int> initial_list;

  for (int i = 0; i <= 50; ++i){
    initial_list.push_back(i);
  }

  std::function<bool(int)> predicate = [](const int& a){
    return a % 2 == 0;
  };

  std::list<int> end_list = filter(initial_list, predicate);

  for (auto e : end_list){
    std::cout << e << " ";
  }
  std::cout << std::endl;

  return 0;
}

尝试支持任意容器时的错误代码:

template <typename T, typename U>
T<U> filter (T<U>& l, std::function<bool(U)> p){
  for (auto it = l.begin(); it != l.end(); ++it){
    if (p(*it)){
      continue;
    }
    else {
      it = l.erase(it);
    }
  }
  return l;
}

编译错误信息:

problem5.cpp:6:1: error: ‘T’ is not a template
 T<U> filter (T<U>& l, std::function<bool(U)> p){
 ^
problem5.cpp:6:14: error: ‘T’ is not a template
 T<U> filter (T<U>& l, std::function<bool(U)> p){
              ^

错误原因

原模板参数声明template <typename T, typename U>中,T被当作普通类型而非模板类型,但实际使用时T是容器模板(如std::list、std::vector),需要用模板模板参数来声明这种模板类型的参数。

另外原代码存在逻辑问题:直接在输入容器上调用erase修改了原容器,不符合filter函数“返回新容器、不修改原数据”的语义。

正确实现方案

1. 修正模板参数

使用模板模板参数声明容器类型,同时用通用的谓词类型替代std::function以提升性能。

2. 重构逻辑:创建新容器返回

遍历原容器,将满足谓词的元素插入新容器,避免修改原容器。

完整代码:

#include <iostream>
#include <list>
#include <vector>
#include <functional>

// 支持任意容器的通用filter函数
template <template <typename...> typename Container, typename T, typename Predicate>
Container<T> filter(const Container<T>& input_container, Predicate predicate) {
    Container<T> result;
    for (const auto& elem : input_container) {
        if (predicate(elem)) {
            result.push_back(elem);
        }
    }
    return result;
}

int main() {
    // 测试std::list
    std::list<int> int_list;
    for (int i = 0; i <= 20; ++i) {
        int_list.push_back(i);
    }
    auto even_list = filter(int_list, [](int num) { return num % 2 == 0; });
    
    std::cout << "过滤后的std::list(偶数):";
    for (int num : even_list) {
        std::cout << num << " ";
    }
    std::cout << "\n";

    // 测试std::vector
    std::vector<std::string> str_vec = {"apple", "banana", "cherry", "date", "elderberry"};
    auto long_str_vec = filter(str_vec, [](const std::string& str) { return str.size() >= 6; });
    
    std::cout << "过滤后的std::vector(长度≥6的字符串):";
    for (const auto& str : long_str_vec) {
        std::cout << str << " ";
    }
    std::cout << "\n";

    return 0;
}

关键说明

  • 模板模板参数:template <typename...> typename Container声明Container是一个接受任意数量模板参数的容器模板,适配std::list、std::vector等标准容器。
  • 通用谓词:使用typename Predicate作为谓词参数,支持lambda、函数指针、函数对象等任意可调用类型,比std::function更高效(避免类型擦除开销)。
  • 无副作用:创建新容器存储结果,原输入容器保持不变,符合函数式编程中filter的预期行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 16:55:19