15

我想编写一个模板函数,它接受 2 个值和一个仿函数或 lambda。该函数使用这些值调用函子并返回结果。

template <typename T, typename Fn> 
_ReturnTypeOfPred_ Apply(T x, T y, Fn fn)
  {
  return fn(x, y);
  }

问题:我怎样才能定义返回类型Apply等于返回类型Fn?它不一定等于T,就像这个函子的例子一样

template <typename T> 
auto Sum(T x, T y) -> decltype(x+y)
  {
  return x+y;
  }

更新

第一个例子过于简单化了。这个应该工作吗?

template <typename TContainer, typename Fn> 
auto Apply(const TContainer& x, const TContainer& y, Fn fn) -> decltype(fn(x.front(), y.front()))
  {
  return fn(x.front(), y.front());
  }

如果我重复返回类型的return表达式,它总是有效吗?decltype有没有更优雅的方式?

4

1 回答 1

18

你快到了;只需使用decltype

template <typename T, typename Fn> 
auto Apply(T x, T y, Fn fn) -> decltype(fn(x, y))
{
  return fn(x, y);
}

您可以使用std::result_ofstd::result_of 和 decltype 之间的区别)但是为什么要麻烦呢?

template <typename T, typename Fn> 
typename std::result_of<Fn, T, T>::type Apply(T x, T y, Fn fn)
{
  return fn(x, y);
}

关于后续问题:对于一个函数

auto fn(<args>) -> <return-type> { return <expression>; }

替换通常return-type起作用,但容易出错。例如,考虑:decltype(<expression>)

auto f(char c) -> decltype(std::string() += c) { return std::string() += c; }

decltype将产生std::string &,您的函数将返回对本地的左值引用!这必须更改为:

auto f(char c) -> std::remove_reference<decltype(std::string() += c)>::type {
    return std::string() += c;
}

在其他情况下,<expression>可能会产生一个不可返回的值,例如不可复制、包含 lambda 等。

于 2012-08-17T12:25:07.217 回答