std::reference_wrapper
を理解しようとしています。
次のコードは、参照ラッパーが参照とまったく同じように動作しないことを示しています。
#include <iostream>
#include <vector>
#include <functional>
int main()
{
std::vector<int> numbers = {1, 3, 0, -8, 5, 3, 1};
auto referenceWrapper = std::ref(numbers);
std::vector<int>& reference = numbers;
std::cout << reference[3] << std::endl;
std::cout << referenceWrapper.get()[3] << std::endl;
// I need to use get ^
// otherwise does not compile.
return 0;
}
私がそれを正しく理解していれば、暗黙的な変換はメンバー関数の呼び出しには適用されません。これは固有の制限ですか? std::reference_wrapper::get
を頻繁に使用する必要がありますか?
別のケースはこれです:
#include <iostream>
#include <functional>
int main()
{
int a = 3;
int b = 4;
auto refa = std::ref(a);
auto refb = std::ref(b);
if (refa < refb)
std::cout << "success" << std::endl;
return 0;
}
これは正常に機能しますが、main
定義の上にこれを追加すると:
template <typename T>
bool operator < (T left, T right)
{
return left.someMember();
}
コンパイラはテンプレートをインスタンス化しようとし、暗黙的な変換と組み込み演算子を忘れます。
この動作は固有のものですか、それともstd::reference_wrapper
について重要な何かを誤解していますか?
クラス_std::reference_wrapper<T>
_は、暗黙の変換演算子を_T&
_に実装します。
_operator T& () const noexcept;
_
より明確なゲッター:
_T& get() const noexcept;
_
暗黙の演算子は、T
(または_T&
_)が必要なときに呼び出されます。例えば
_void f(some_type x);
// ...
std::reference_wrapper<some_type> x;
some_type y = x; // the implicit operator is called
f(x); // the implicit operator is called and the result goes to f.
_
ただし、T
が必ずしも必要ではない場合があり、この場合はget
を使用する必要があります。これは、ほとんどの場合、自動型推論コンテキストで発生します。例えば、
_template <typename U>
g(U x);
// ...
std::reference_wrapper<some_type> x;
auto y = x; // the type of y is std::reference_wrapper<some_type>
g(x); // U = std::reference_wrapper<some_type>
_
上記の_some_type
_の代わりに_std::reference_wrapper<some_type>
_を取得するには
_auto y = x.get(); // the type of y is some_type
g(x.get()); // U = some_type
_
または、上記の最後の行をg<some_type>(x);
で置き換えることもできます。ただし、テンプレート化された演算子(たとえば、ostream::operator <<()
)の場合、型を明示的に指定できないと思います。