15

2つの値とファンクターまたはラムダを受け入れるテンプレート関数を作成したいと思います。この関数は、これらの値を使用してファンクターを呼び出し、結果を返します。

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; }

ここでdecltypeyieldが生成std::string &され、関数はローカルへの左辺値参照を返します。これは次のように変更する必要があります。

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

他の場合で<expression>は、例えば、コピーできない、ラムダを含むなどの理由で返されない値を生成する可能性があります。

于 2012-08-17T12:25:07.217 に答える