【问题标题】:Auto deduce type of function in template自动推断模板中的函数类型
【发布时间】:2018-04-12 14:40:31
【问题描述】:

我有简单的map 实现和简单的id(身份):

template <typename T>
T map(const T& x, std::function<decltype(x[0])(decltype(x[0]))> f) {
    T res(x.size());
    auto res_iter = begin(res);
    for (auto i(begin(x)); i < end(x); ++i) {
        *res_iter++ = f(*i);
    }
    return res;
}

template <typename T>
T id(T& x) {return x;}

当我打电话时

vector<int> a = {1,2,3,4,5,6,7,8,9};
map(a, id<const int>);

它有效,但我想在没有类型说明的情况下调用它,如下所示:

map(a, id);

当我这样做时,我得到了错误:

error: cannot resolve overloaded function 'id' based on conversion to type 'std::function<const int&(const int&)>'
 map(a, id);
          ^

当错误包含右有界类型时,我该如何解决?为什么编译器不能从 map 的上下文中推断出 id 的类型?

【问题讨论】:

  • 我将把我之前未回答的有用部分变成评论:通常最好为函数输入(以及类型签名的文档)提供一个普通模板参数,而不是std::function。它不能解决问题,但类似于:template&lt;typename T, typename F&gt; T map(const T&amp; x, F&amp;&amp; f)。像 std::function 这样的东西在这里会很棒 if C++ 类型推断走得更远。

标签: c++ templates c++14 generic-programming


【解决方案1】:

如果您在符合 C++14 的环境中,有一种非常简洁的方法可以做到这一点。不要使用 std::function 和模板类,而是使用无约束的转发引用和通用 lambda,如下所示:

#include <vector>

template <typename T,typename F>
T map(const T& x, F &&f) {
  T res(x.size());
  auto res_iter = begin(res);
  for (auto i(begin(x)); i < end(x); ++i) {
    *res_iter++ = f(*i);
  }
  return res;
}

auto id = [](auto x) { return x;};

int main()
{
  std::vector<int> v = {1, 2, 3, 4};
  auto v2 = map(v, id);
}

在 C++11 中,您必须将泛型 lambda 替换为其 operator() 是模板化方法的函子,如下所示:

struct {
  template<typename T>
  T operator()(T x) const
  {
    return x;
  }
} id;

在 C++98 语法中,您将无法使用转发引用,因此您将不得不考虑复制和仿函数可变性问题。

【讨论】:

  • 可以在这个版本的map中以某种方式使用模板吗?
  • 我不确定您所说的“可以使用模板吗?”是什么意思?你能详细说明一下吗?
【解决方案2】:

这是因为id 不是函数。这是一个函数模板!

这意味着id是一个模板,它可以生成id&lt;const int&gt;这样的函数,但它本身并不是一个真正的函数。

在运行时没有id,只有id创建的函数实例。

【讨论】:

  • 但是当编译器看到id的调用以int作为参数时,它不应该创建id&lt;int&gt;的实例吗?
  • 那有什么办法呢?
  • 解决方案是使用id&lt;const int&gt;static_castLIFT macro
  • 问题是“我怎么能……”,答案是“因为……”-1
  • @Slava:很公平
猜你喜欢
  • 2021-03-04
  • 2015-09-05
  • 1970-01-01
  • 2019-09-12
  • 2016-11-05
  • 1970-01-01
  • 2016-07-16
  • 2016-03-16
  • 1970-01-01
相关资源
最近更新 更多