6

完全な転送にはいくつかの問題があります。

私の現在の理解レベルは次のとおりです。グルー テンプレート + 右辺値参照 + std::forward と、テンプレート推定ルールが通常と同じ意味を持たない特別な魔法のモードがアクティブになりますが、完全な転送を可能にするように作られています。例 :

template <typename T>
void outer(T&& t)
{
   inner(std::forward<T>(t)); // perfect forwarding activated
}

しかし、もし T が実際にテンプレート化されたクラスだったらどうなるでしょうか? たとえば、 std::tuple を完全転送するにはどうすればよいですか? 上記のように T&& を使用すると、タプルに含まれるオブジェクトの型情報がすべて失われます。
ただし、次のコードは機能しません。

template <typename... Args>
void outer(std::tuple<Args...>&& t) 
{
   inner(std::forward<std::tuple<Args...>>(t));
   use_args_types_for_something_else<Args...>(); // I need to have Args available
}

int main()
{
   std::tuple<int, double, float> t(4, 5.0, 4.0f);
   outer(t);
}

最後の gcc スナップショットは次のように述べています。

error: cannot bind 'std::tuple<int, double, float> lvalue to
std::tuple<int, double, float>&&

明らかに、左辺値が右辺値参照にバインドできない一般的な非テンプレートのケースにまだいます。「完全前進モード」が発動しない

だから私は卑劣になり、自分のタプルをテンプレート template として渡そうとしました:

template <
  typename... Args
  template <typename...> class T
>
void outer(T<Args...>&& t) 
{
   inner(std::forward<T<Args...>>(t));
   use_args_type_for_something_else<Args...>(); 
}

しかし、私はまだ同じエラーが発生します。

4

1 に答える 1

3

完全転送は、パラメーターの型が関数のテンプレート型である場合にのみ機能するため、完全転送を実現する唯一の方法は、最初の例のようになります。

template <typename T>
void outer(T&& t)
{
   inner(std::forward<T>(t)); // perfect forwarding activated
}

上記は、またはTとして推定される特殊なケースであるため、機能します。SomeType&SomeType&&

ただし、これは、タプル要素の型情報が完全に失われることを意味するものではありません。それはまだ取得可能です (ただし、可変個引数テンプレート パックを typedef できるとは思いません)。たとえば、次use_args_types_for_something_elseのように呼び出すことができます。

template <class T>
struct call_uses_args;

template <class ...Args>
struct call_uses_args<std::tuple<Args...>>
{
    void call() const { use_args_types_for_something_else<Args...>(); }
};

template <typename TupleT>
void outer(TupleT&& t)
{
   inner(std::forward<TupleT>(t));
   call_uses_args<typename std::remove_reference<TupleT>::type>().call();
}

ただし、適切な一般的な解決策はないかもしれませんが、そのような状況がまれであることを願っています。(たとえば、この特定の例では、単にオーバーロードする方が簡単かもしれませんouter。)

于 2011-11-26T11:07:40.550 に答える