在函数模板中使用lambda,不能推导出类型,makeSet()用例

时间:2017-02-20 13:48:38

标签: c++ c++11 templates lambda type-deduction

我想要实现的是一个接受三个参数的makeSet()函数,一对迭代器和一个转换值的函数。

一个用例可能是从一系列值创建一个集合并进行转换,例如,将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。

有任何解决方案或解决方法吗? 如果你能告诉我正确的方法,我将非常感激。

2 个答案:

答案 0 :(得分:9)

lambda表达式的类型是未命名的类类型(其闭包类型),而不是std::function。因此,您无法从中推断出std::functionMonad

您最好的选择是执行标准库所做的事情,并简单地接受任何内容作为谓词:

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建议的{{1} }})。

另外,为避免重新发明轮子,您可能需要查看Boost.Range库。

答案 1 :(得分:1)

&#34;你越是疏忽管道,就越容易阻止排水管。&#34; - Scotty,Star Trek III。

没有必要过度设计模板功能,就像那样。只需使用转发引用,让C ++ 17编译器解决所有问题。

<?php

defined('BASEPATH') OR exit('No direct script access allowed');

date_default_timezone_set('Asia/Kolkata');