web-dev-qa-db-ja.com

std :: make_Tupleは参照を行いません

私はstd::Tupleを参照と組み合わせて実験しています:

#include <iostream>
#include <Tuple>

int main() {
  int a,b;
  std::Tuple<int&,int&> test(a,b);
  std::get<0>(test) = 1;
  std::get<1>(test) = 2;
  std::cout << a << ":" << b << std::endl;

  // doesn't make ref, not expected
  auto test2 = std::make_Tuple(a,b);
  std::get<0>(test2) = -1;
  std::get<1>(test2) = -2;
  std::cout << a << ":" << b << std::endl;

  int &ar=a;
  int &br=b;
  // why does this not make a Tuple of int& references? can we force it to notice?
  auto test3 = std::make_Tuple(ar,br);
  std::get<0>(test3) = -1;
  std::get<1>(test3) = -2;
  std::cout << a << ":" << b << std::endl;
}

ここにある3つの例のうち、最初の2つは期待どおりに機能します。しかし、3番目のものはそうではありません。 autoタイプ(test3)はtestのタイプ(つまり、std::Tuple<int&,int&>)と同じであると期待していました。

std::make_Tupleは自動的に参照のタプルを作成できないようです。何故なの?そのタイプの何かを自分で明示的に構築する以外に、これを実現するために何ができますか?

(コンパイラはg ++ 4.4.5でした 4.5を使用しても変更されません

38
Flexo

forward_as_Tupleを試してください:

auto test3 = std::forward_as_Tuple(ar,br);
32
Howard Hinnant

std::tieconst以外の参照を作成します。

auto ref_Tuple = std::tie(a,b); // decltype(ref_Tuple) == std::Tuple<int&, int&>

const参照の場合は、std::crefラッパー関数が必要です。

auto cref_Tuple = std::make_Tuple(std::cref(a), std::cref(b));

または、単にas_constヘルパーを使用して、変数をstd::tieに渡す前に修飾します。

template<class T>
T const& as_const(T& v){ return v; }

auto cref_Tuple = std::tie(as_const(a), as_const(b));

または、凝ったものにしたい場合は、独自のctieを記述します(std::tieas_constを再利用します):

template<class... Ts>
std::Tuple<Ts const&...> ctie(Ts&... vs){
  return std::tie(as_const(vs)...);
}

auto cref_Tuple = ctie(a, b);
55
Xeo

どうですか:

auto test3 = std::make_Tuple(std::ref(a),std::ref(b));
4
sbk

理由:make_Tupleパラメーターはconst参照(const T&)によって渡されるため、int&を渡すと、Tintと一致します。 Tint&であると推定された場合、パラメーターはconst T&&となり、コンパイルエラーが発生します。

3