私は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を使用しても変更されません )
forward_as_Tuple
を試してください:
auto test3 = std::forward_as_Tuple(ar,br);
std::tie
はconst
以外の参照を作成します。
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::tie
とas_const
を再利用します):
template<class... Ts>
std::Tuple<Ts const&...> ctie(Ts&... vs){
return std::tie(as_const(vs)...);
}
auto cref_Tuple = ctie(a, b);
どうですか:
auto test3 = std::make_Tuple(std::ref(a),std::ref(b));
理由:make_Tuple
パラメーターはconst参照(const T&
)によって渡されるため、int&
を渡すと、T
はint
と一致します。 T
がint&
であると推定された場合、パラメーターはconst T&&
となり、コンパイルエラーが発生します。