std::reference_wrapper
| ヘッダ <functional> で定義
|
||
template< class T > class reference_wrapper; |
(C++11以上) | |
std::reference_wrapper はコピー可能、代入可能なオブジェクトに参照をラップするクラステンプレートです。 通常は参照を保持できない標準コンテナ (std::vector のような) の内部に参照を格納するための仕組みとしてよく使用されます。
具体的には、 std::reference_wrapper は T 型のオブジェクトへの参照または関数への参照を中心とする CopyConstructible かつ CopyAssignable なラッパーです。 std::reference_wrapper のインスタンスはオブジェクト (コピーしたりコンテナに格納したりできる) ですが、ベースとなる型を参照で取る関数で引数として使用できるように、 T& に暗黙に変換されます。
格納されている参照が Callable である場合、 std::reference_wrapper はそれと同じ引数で呼び出し可能です。
ヘルパー関数 std::ref および std::cref が std::reference_wrapper オブジェクトを生成するためによく使用されます。
std::reference_wrapper は std::bind や std::thread のコンストラクタ、ヘルパー関数 std::make_pair および std::make_tuple にオブジェクトを参照渡しするためにも使用されます。
|
|
(C++17以上) |
|
|
(C++20以上) |
メンバ型
| 型 | 定義 |
type
|
T
|
result_type(C++17で非推奨)(C++20で削除)
|
T が関数であれば T の戻り値の型。 そうでなければ定義されません
|
argument_type(C++17で非推奨)(C++20で削除)
|
1) T が A1 型の引数をひとつ取る関数または関数ポインタの場合、 argument_type は A1 です2) |
first_argument_type(C++17で非推奨)(C++20で削除)
|
1) T が型 A1 および A2 の2つの引数を取る関数または関数ポインタの場合、 first_argument_type は A1 です2) |
second_argument_type(C++17で非推奨)(C++20で削除)
|
1) T が型 A1 および A2 の2つの引数を取る関数または関数ポインタの場合、 second_argument_type は A2 です2) |
メンバ関数
| 新しい std::reference_wrapper オブジェクトに参照を格納します (パブリックメンバ関数) | |
| std::reference_wrapper を再束縛します (パブリックメンバ関数) | |
| 格納されている参照にアクセスします (パブリックメンバ関数) | |
| 格納されている関数を呼びます (パブリックメンバ関数) |
推定ガイド(C++17以上)
実装例
namespace detail {
template <class T> T& FUN(T& t) noexcept { return t; }
template <class T> void FUN(T&&) = delete;
}
template <class T>
class reference_wrapper {
public:
// 型
typedef T type;
// 構築、コピー、破棄
template <class U, class = decltype(
detail::FUN<T>(std::declval<U>()),
std::enable_if_t<!std::is_same_v<reference_wrapper, remove_cvref_t<U>>>()
)>
constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::FUN<T>(std::forward<U>(u))))
: _ptr(std::addressof(detail::FUN<T>(std::forward<U>(u)))) {}
reference_wrapper(const reference_wrapper&) noexcept = default;
// 代入
reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
// アクセス
constexpr operator T& () const noexcept { return *_ptr; }
constexpr T& get() const noexcept { return *_ptr; }
template< class... ArgTypes >
constexpr std::invoke_result_t<T&, ArgTypes...>
operator() ( ArgTypes&&... args ) const {
return std::invoke(get(), std::forward<ArgTypes>(args)...);
}
private:
T* _ptr;
};
// 推定ガイド
template<class T>
reference_wrapper(T&) -> reference_wrapper<T>;
|
例
参照のコンテナとしての reference_wrapper の使用をデモンストレーションします。 これにより複数のインデックスを使用して同じコンテナにアクセスすることが可能となります。
#include <algorithm>
#include <list>
#include <vector>
#include <iostream>
#include <numeric>
#include <random>
#include <functional>
int main()
{
std::list<int> l(10);
std::iota(l.begin(), l.end(), -4);
std::vector<std::reference_wrapper<int>> v(l.begin(), l.end());
// list に shuffle を使用することはできません (ランダムアクセスを要求します) が、 vector には使用できます。
std::shuffle(v.begin(), v.end(), std::mt19937{std::random_device{}()});
std::cout << "Contents of the list: ";
for (int n : l){
std::cout << n << ' ';
}
std::cout << "\nContents of the list, as seen through a shuffled vector: ";
for (int i : v){
std::cout << i << ' ';
}
std::cout << "\n\nDoubling the values in the initial list...\n\n";
for (int& i : l) {
i *= 2;
}
std::cout << "Contents of the list, as seen through a shuffled vector: ";
for (int i : v){
std::cout << i << ' ';
}
}
出力例:
Contents of the list: -4 -3 -2 -1 0 1 2 3 4 5
Contents of the list, as seen through a shuffled vector: -1 2 -2 1 5 0 3 -3 -4 4
Doubling the values in the initial list...
Contents of the list, as seen through a shuffled vector: -2 4 -4 2 10 0 6 -6 -8 8
関連項目
(C++11)(C++11) |
引数から推定される型の std::reference_wrapper を作成します (関数テンプレート) |
(C++11) |
関数オブジェクトに1つ以上の引数をバインドします (関数テンプレート) |