Lambdas and std::function
Lambdas and std::function
我正在努力赶上C++11和所有伟大的新功能。我有点卡在lambdas上。
这是我能够开始工作的代码:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <functional>
using namespace std;
template<typename BaseT, typename Func>
vector<BaseT> findMatches(vector<BaseT> search, Func func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
我想要的是这个:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
基本上,我想将可能的 lambda 缩小到合理的函数子集。我错过了什么?这可能吗?我正在使用GCC/G ++ 4.6。
Stephan T. Lavavej在本视频中解释了为什么这不起作用。基本上,问题在于编译器试图从std::vector
和std::function
参数推断BaseT
。C++ 中的 lambda 不是 std::function
类型,它是一种未命名的、唯一的非联合类型,如果没有捕获列表(空[]
(,则可以转换为函数指针。另一方面,可以从任何可能类型的可调用实体(函数指针、成员函数指针、函数对象(创建std::function
对象。
请注意,我个人不明白为什么要将传入函子限制为该特定签名(除了通过多态函数包装器(如 std::function
(的间接寻址比直接调用函子(甚至可能是内联的(效率低得多(,但这是一个工作版本。基本上,它禁用了std::function
部分的参数推导,仅从std::vector
参数中推导出BaseT
:
template<class T>
struct Identity{
typedef T type;
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Ideone上的活生生的例子。
另一种可能的方法是不直接限制函子类型,而是通过 SFINAE 间接限制:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype(bool(fun(v[0])), void())
{
// ...
}
Ideone上的活生生的例子。
如果fun
不接受类型 T&
的参数或返回类型不可转换为 bool
的参数,则将从重载集中删除此函数。, void()
使f
的返回类型void
。
正如其他海报所揭示的那样,这是 std::function 的模板参数推导。
使第二个代码片段工作的一种直观方法是在调用模板函数时添加基类型:findMatches<int>
。
Xeo没有提到的另一种方法是使用std::is_convertible:
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
它避免将 lamda 包装到 std::function 中,并提供更干净的错误消息。
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- Confusion: decltype vs std::function
- 为什么 std::function 可以作为 std::not2 的参数?
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 传递给std::function template的template参数究竟代表什么
- 将带有unique_ptr的可变 lambda 传递给 const&std::function
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 如何在向量中删除 std::function<void()>?
- 将函数包装器转换为 std::function
- 类型擦除的std::function与虚拟函数调用的开销
- C++ std::function 对于类 exept 的所有实例都是空的(只有 Visual2019 编译器问题)
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 将 lambda 表达式传递给 std::function in C++
- 广义 std::function (std::any 表示可调用对象)
- std::function<std::optional<T>()> 如何与返回 T 的 lambda 兼容?
- std::function std::bind with lambda overload ambiguity
- Clang bug with std::function, std::bind and std::ref?
- 为什么我会收到编译错误"use of deleted function 'std::unique_ptr ..."
- 为什么我不能让 std::function<std::vector<T>::iterator> 绑定到返回该类型的 lambda?
- 回调(std::function/std::bind)与接口(抽象类)的优缺点