web-dev-qa-db-ja.com

これは転送参照ですか?

この例では、右辺値参照と転送参照の違いが、ScottMeyersによって十分に明確にされています。

Widget&& var1 = someWidget;     // here, “&&” means rvalue reference (1)

auto&& var2 = var1;             // here, “&&” does not mean rvalue reference (2)

template<typename T>
void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3)

template<typename T>
void f(T&& param);              // here, “&&”does not mean rvalue reference (4)

基本的に、区別は控除可能なコンテキストがある場合に発生します。したがって、ケース(3)は、vector<...>&&があることを明示的に示していますが、ケース(4)のTは推定され、(参照折りたたみルールを適用した後)「値カテゴリ」の観点から分類されます。

しかし、もう少し複雑なパターンマッチングではどうなりますか?次の場合を例にとってみましょう:

template <template <class...> class Tuple, class... Ts>
void f(Tuple<Ts...>&& arg)
{

}

ここで&&はどういう意味ですか?

21
Lorah Attkins

最後の例では、argは右辺値の参照です。

転送参照はcv非修飾テンプレートパラメーターへの右辺値参照です

およびTuple<Ts...>はテンプレートパラメータではありません。

([temp.deduct.call]からの引用。)

16
Kerrek SB

これは右辺値参照であり、転送参照ではありません。

確実にする最も簡単な方法は、左辺値を渡そうとすることです。失敗した場合は右辺値参照、そうでない場合は転送参照です。

template<typename... Ts>
struct foo {};

//f function definition

int main() {
    foo<int, double> bar;
    f(bar); // fails! Cannot bind lvalue to rvalue reference
    f(foo<int, double>{}); // ok, rvalue is passed
}
11
Rakete1111

参照の転送という概念は標準的な概念ではありません。参照を確認すると便利ですが、正しく理解して処理する場合は、参照演算を理解する必要があります。 (マイヤーの本にもそれについての章があると思います)

転送参照の概念の背後にあるのは、参照演算です。

  • && && = &&
  • &&& =&
  • &&& =&
  • && =&

転送参照を使用してコンパイラテンプレート型の推定をシミュレートしてみましょう

_template<class T>
void foo(T&&);
//...
const int i=42;
foo(i); // the compiler will defines T = const int &
         //          T&&  = const int & && = const int &
         // => the compiler instantiates void foo<const int &>(const int &);
foo(6*7);// the compiler will defines T = int
         //          T&&  = int &&
         // the compiler instantiates  void foo<int>(int &&);
_

このような状況では、テンプレートfooのインスタンス化により、左辺値参照によって引数を取る関数、または引数右値参照を取る関数が生成されます。転送参照は、テンプレートタイプの推定に応じて、右辺値参照または左辺値参照のいずれかになります。このような状況では、パラメーターは左辺値またはx値のいずれかとして渡されるため、このように名前が付けられます。これはT&& std::forward<T>(T&& a)の仕事です。

関数を宣言すると、次のようになります。

_ template<class T>
 void foo(ATemplateClass<T> && a);
_

コンパイラーによってTに対して推定されたタイプが何であれ、右辺値参照パラメーターを取得します。

4
Oliv