我想节省一些打字,因此定义如下:
using namespace std;
vector<MyClass> vec;
auto vecsort = bind(sort, vec.begin(), vec.end(), [] (MyClass const &a, MyClass const &b) {
// custom comparison function
});
vecsort(); // I want to use vecsort() a lot afterwards
由于某些原因,这不能编译 - 为什么?
使用提升不是一种选择。
最小的工作示例:
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
using namespace std;
int main() {
vector<pair<int, int>> vec;
for (int i = 0; i < 10; i++)
vec.push_back(make_pair(10 - i, 0));
auto vecsort = bind(sort, vec.begin(), vec.end(), [] (pair<int, int> const &a, pair<int, int> const &b) {
return a.first < b.first;
});
vecsort();
}
错误:
error: no matching function for call to 'bind(<unresolved overloaded function type>, std::vector<std::pair<int, int> >::iterator, std::vector<std::pair<int, int> >::iterator, main()::__lambda0)'
答案 0 :(得分:12)
问题是std::sort
不是函数对象。它是一个功能模板。处理该问题的最简单方法是创建一个简单的包装器对象:
struct sorter {
template <typename RndIt, typename Cmp>
void operator()(RndIt begin, RndIt end, Cmp cmp) {
std::sort(begin, end, cmp);
}
};
现在你可以使用
std::bind(sorter(), vec.begin(), vec.end(), [](...){ ... });
答案 1 :(得分:7)
其他人已经提到过为什么它不能编译,但是这个备用解决方案对你有用吗?这使用另一个lambda而不是bind来创建std :: function。
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;
int main() {
vector<pair<int, int>> vec;
for (int i = 0; i < 10; i++) {
vec.push_back(make_pair(10 - i, 0));
}
auto vecsort = [&vec] {
sort(vec.begin(), vec.end(),
[] (pair<int, int> const &a, pair<int, int> const &b) {
return a.first < b.first;
});
};
// vecsort will work as long as vec is in scope.
// vecsort will modify the original vector.
vecsort();
for (auto i : vec) {
std::cout << '(' << i.first << ", " << i.second << ") ";
}
std::cout << endl;
vec.push_back(make_pair(-42, 0));
vecsort();
for (auto i : vec) {
std::cout << '(' << i.first << ", " << i.second << ") ";
}
std::cout << endl;
}
输出:
(1, 0) (2, 0) (3, 0) (4, 0) (5, 0) (6, 0) (7, 0) (8, 0) (9, 0) (10, 0)
(-42, 0) (1, 0) (2, 0) (3, 0) (4, 0) (5, 0) (6, 0) (7, 0) (8, 0) (9, 0) (10, 0)
看到它在这里运行: http://ideone.com/W2YQKW
答案 2 :(得分:3)
这是一个有用的宏来解决这个问题。它的作用是创建一个匿名struct
,其实例表示在特定上下文中调用特定函数名(通过字符串值)的重载集。
C ++遗憾地缺乏这样的功能。如果只有人会向C ++标准化委员会提出建议。唉。 1
#define OVERLOAD_SET(FUNCTION_NAME) struct { template<typename... Args>\
auto operator()(Args&&... args) const->\
decltype(FUNCTION_NAME(std::forward<Args>(args)...))\
{ return (FUNCTION_NAME(std::forward<Args>(args)...)); } \
}
在全球范围内:
OVERLOAD_SET( std::sort ) sorter;
然后,在使用时:
std::bind( sorter, vec.begin(), vec.end(), [](...) {...} );
问题是std::sort
是一个template
(或者可能是一组通过重载选择的template
!),它们在被调用时生成函数,而不是实际函数。它看起来像一个函数,但事实并非如此。并且template
和过载集不能直接传递给其他函数。
顺便说一下,可以通过添加OVERLOAD_SET
来改进上面的template<typename R, typename... Args> operator R(*)(Args...)() const
宏,这允许OVERLOAD_SET
隐式地转换为特定的函数指针,但这是超出了这个问题的范围。
1 Xeo提出了这样的建议。