在函数模板中使用lambda,无法推断类型,makeSet()用例
use lambda in function template, can't deduce type, makeSet() use case
我想实现的是一个akeet()函数,接受三个参数,一对迭代器和一个转换值的函数。
一种用例可能是从一系列值创建一个集合,并进行转换,例如,将std::map<K,V>
转换为std::set<std::pair<V,K>>.
客户端代码看起来像
auto s = makeSet(hash.begin(), hash.end(),
[](std::pair<int,int> x) { return std::make_pair(x.second, x.first); });
我目前的尝试如下,
// (commented code are some other *failed* attempt).
template <typename Iterator,
typename T = typename std::iterator_traits<Iterator>::value_type,
template<typename ... > class Monad, typename R >
// typename R, typename Monad = std::function<R(T)> >
std::set<R> makeSet(Iterator first, Iterator last, Monad<R,T> f) {
std::set<R> res;
for (; first != last; ++first) res.insert(f(*first));
return res;
}
,但不幸的是不起作用。这个问题似乎无法推断出R。
有任何解决方案或解决方法吗?如果您能告诉我正确的方法,我将非常感谢。
lambda表达式的类型是未命名的类型(其闭合类型),而不是std::function
。因此,您不能从中推导std::function
或Monad
。
您最好的选择是做标准库的所作所为,只是接受任何东西作为谓词:
template <
class Iterator,
class UnaryFunction
>
auto makeSet(Iterator first, Iterator last, UnaryFunction f) -> std::set<decltype(f(*first))>
{
std::set<decltype(f(*first))> res;
for (; first != last; ++first) res.insert(f(*first));
return res;
}
请注意,您可能必须将decltype
包装在std::remove_reference
和/或std::remove_cv
中才能覆盖所有角色案例(或,如@yakk,std::decay
)。
另外,为了避免重新发明轮子,您可能需要查看boost.range库。
"您越多地思考管道,就越容易停止排水管。" - 斯科蒂,星际迷航III。
无需过度设计模板功能。只需使用转发参考,然后让您的C 17编译器弄清楚所有内容。
#include <set>
#include <map>
#include <utility>
#include <type_traits>
// (commented code are some other *failed* attempt).
template <typename Iterator, typename Lambda>
auto makeSet(Iterator first, Iterator last, Lambda &&f) {
typedef typename std::remove_reference<decltype(first->first)>::type const_first_t;
typedef typename std::remove_const<const_first_t>::type first_t;
typedef typename std::remove_reference<decltype(first->second)>::type second_t;
typedef std::pair<first_t, second_t> R;
std::set<R> res;
for (; first != last; ++first) res.insert(f(*first));
return res;
}
void foo()
{
std::map<int, int> m;
std::set<std::pair<int, int>> s =
makeSet(m.begin(), m.end(),
[](const auto &x)
{
return std::make_pair(x.second, x.first);
});
}
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 在函数模板中使用lambda,无法推断类型,makeSet()用例