C++11如何使用lambda函数模板做参数

浏览:48日期:2023-03-30

问题描述

开始使用C++11特性,碰到一些问题。以下写了一个快速排序的函数模板,划分操作的比较函数使用一个std::function<int(T,T)>的参数接收,而在main中使用函数模板接收一个lambda函数[](int a, int b) -> int {return a < b;}时报错,函数不匹配。这里该如何处理?

#include <iostream>#include <functional>template <typename T>void Swap(T *a, T *b) { T tmp = *a; *a = *b; *b = tmp;}template <typename T>int partition(T array[], int low, int high, const std::function<int(T, T)> &cmp) { int i = low - 1; T x = array[high]; for (int j = low; j < high; j++) {if (cmp(array[j], x)) { i++; Swap(&array[j], &array[i]);} } Swap(&array[i + 1], &array[high]); return i + 1;}template <typename T>void quicksort(T array[], int low, int high, const std::function<int(T, T)> &cmp) { if (low < high) {int mid = partition(array, low, high, cmp);quicksort(array, low, mid - 1, cmp);quicksort(array, mid + 1, high, cmp); }}int main() { std::cout << 'Hello, World!' << std::endl; int arr[] {5, 3, 9, 1, 6, 2}; quicksort(arr, 0, 5, [](int a, int b) -> int { return a < b; }); for(auto item: arr) {std::cout << item << ' '; } std::cout << std::endl; return 0;}

报错信息:E:ProjectDesignPatternmain.cpp: In function ’int main()’:E:ProjectDesignPatternmain.cpp:39:6: error: no matching function for call to ’quicksort(int [6], int, int, main()::<lambda(int, int)>)’ }); ^E:ProjectDesignPatternmain.cpp:26:6: note: candidate: template<class T> void quicksort(T*, int, int, const std::function<int(T, T)>&) void quicksort(T array[], int low, int high, const std::function<int(T, T)> &cmp) { ^E:ProjectDesignPatternmain.cpp:26:6: note: template argument deduction/substitution failed:E:ProjectDesignPatternmain.cpp:39:6: note: ’main()::<lambda(int, int)>’ is not derived from ’const std::function<int(T, T)>’ }); ^

问题解答

回答1:

lambda转换成const std::function<int(T, T)>&前无法帮助推导出T的类型.

可以增加个辅助类先确定std::function的类型,再进行lambda的隐式转换.

tempalte<typename T>struct type_deduce{ using type = T;};template<typename T>void quicksort(T array[], int low, int high, const typename type_deduce<std::function<int(T, T)>>::type& cmp)回答2:

类型推导时不会进行用户自定义的类型转换,即不会进行从lambda表达式到std::function的转换。所以这里跪了。

你这里需要的是一个BinaryPredicate。直接写Fn &&fn即可。然后对Fn进行一下BinaryPredicate的检查。

或者把T变成一个non deduction context,比如

template <typename T>void quicksort(T array[], int low, int high, const std::function<int (decltype(std::declval<T>()),decltype(std::declval<T>()))> &cmp)

或者

template <class T>struct BinaryPredicateType { using type = std::function<int (T, T)>;};template <typename T>void quicksort(T array[], int low, int high, const typename BinaryPredicateType<T>::type &cmp)

相关文章: