C++自定义模板排序函数的std::function类型适配问题及解决方案
解决C++通用排序函数的类型适配问题
你遇到的核心问题是比较器的类型绑定过死,导致模板无法灵活适配不同类型的比较需求。让我们一步步拆解问题并修复它:
原代码的核心问题
原sorting函数的声明:
void sorting(vector<T>& files, int beginning, int end, std::function<bool(int, int)> compare)
这里有两个关键问题:
- 硬编码了
std::function<bool(int, int)>,意味着只能接收比较int类型的函数/lambda,对于double等其他类型,lambda的签名不匹配,会直接编译失败。 - 即使改成
std::function<bool(T, T)>,std::function的类型擦除会带来额外的性能开销,而且模板推导无法自动匹配lambda的具体类型,需要显式转换,不够灵活。
另外,原median_size函数也有小问题:返回类型是int,但应该返回T(因为处理的是vector<T>),而且参数传值会导致整个vector拷贝,效率低下。
修复方案
我们可以通过将比较器也作为模板参数来解决这个问题,这样编译器会自动推导比较器的具体类型(包括lambda的闭包类型),既避免类型擦除的开销,又能完美适配任意符合要求的比较逻辑。同时修正median函数的返回类型和参数传递方式。
修复后的完整代码
#include <iostream> #include <vector> #include <algorithm> #include <functional> #include <memory> // 为了std::make_unique using std::vector; using std::cout; using std::swap; using std::make_unique; template <class T> T median(const vector<T>& values, int beginning, int end) { T a = values[beginning], b = values[(end + beginning) / 2], c = values[end - 1]; if ((a < b && a > c) || (a > b && a < c)) return a; else if ((b < a && b > c) || (b > a && b < c)) return b; else return c; } template <typename T, typename F> void sorting(vector<T>& values, int beginning, int end, F compare) { int left = beginning, right = end; T pivot = median(values, beginning, end); while (left <= right) { while (compare(values[left], pivot)) left++; while (compare(pivot, values[right])) right--; if (left <= right) { swap(values[left], values[right]); left++; right--; } } // 递归处理子数组,优化边界判断逻辑 if (beginning < right) sorting(values, beginning, right, compare); if (left < end) sorting(values, left, end, compare); } int main() { // 测试int类型数组排序 vector<int> values{ 2135,2134,1236,21366,12312,2351232 }; std::sort(std::begin(values), std::end(values), [](int a, int b) { return a < b; }); cout << "Sorted int values:\n"; for (auto value : values) cout << value << "\n"; cout << "\n"; // 演示lambda捕获智能指针 auto p = make_unique<int>(65); cout << "Original pointer value: " << *p << "\n"; auto lambda = [&p]() { cout << "Lambda captured value: " << *p << "\n"; }; lambda(); cout << "\n"; // 测试double类型数组排序 vector<double> values2{ 2135.2135,2134.12365,1236.11,1236.12,21366,12312,235122}; sorting(values2, 0, values2.size() - 1, [](double a, double b) { return a < b; } ); cout << "Sorted double values:\n"; for (auto value : values2) cout << value << "\n"; }
关键修复点说明
- 比较器模板化:新增模板参数
F,让编译器自动推导比较器的类型(比如lambda的闭包类型),无需std::function,既高效又灵活。 - 修正median函数:返回类型改为
T,参数使用const vector<T>&避免不必要的拷贝,同时函数名改为更准确的median。 - 安全的命名空间使用:替换
using namespace std;为具体的using声明,避免命名空间污染。 - 优化递归边界:原代码的边界判断
right - beginning > 0简化为beginning < right,逻辑更清晰直观。
内容的提问来源于stack exchange,提问作者Michał Turek
相关产品推荐
相关产品推荐

