functional_reference_wrapper
functional_reference_wrapper (참조 래퍼)
std::reference_wrapper는 참조를 복사하고 대입할 수 있는 객체로 감싸는 클래스 템플릿이에요. 이 페이지에서는 std::reference_wrapper의 정의, 멤버 타입, 멤버 함수, 비멤버 함수, 구현 예시와 사용 예제를 설명할게요.
출처: cppreference
본문
정의
<functional> 헤더에 정의되어 있어요.
template < class T > class reference_wrapper ; |
(C++11 이후) |
std::reference_wrapper는 참조를 복사 가능하고 대입 가능한 객체로 감싸는 클래스 템플릿이에요. 구체적으로, 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에 객체를 참조로 전달할 때 사용돼요. 또한 일반적으로 참조를 보관할 수 없는 표준 컨테이너(예: std::vector)에 참조를 저장하는 메커니즘으로도 사용할 수 있어요.
std::reference_wrapper는 TriviallyCopyable임이 보장돼요. |
(C++17 이후) |
|---|---|
T는 불완전 타입일 수 있어요. |
(C++20 이후) |
멤버 타입
| type | 정의 |
|---|---|
type |
T |
result_type (C++17에서 deprecated, C++20에서 제거) |
T가 함수라면 T의 반환 타입. 그렇지 않으면 정의되지 않음. |
argument_type (C++17에서 deprecated, C++20에서 제거) |
T가 하나의 인자 A1을 받는 함수 또는 함수 포인터라면 argument_type은 A1이고, T가 인자를 받지 않는 클래스 T0의 멤버 함수 포인터라면 argument_type은 cv 한정이 적용된 T0*이며, T가 멤버 타입 T::argument_type을 가진 클래스 타입이라면 argument_type은 그 별칭이에요. |
first_argument_type (C++17에서 deprecated, C++20에서 제거) |
T가 두 인자 A1과 A2를 받는 함수 또는 함수 포인터라면 first_argument_type은 A1이고, T가 하나의 인자를 받는 클래스 T0의 멤버 함수 포인터라면 first_argument_type은 cv 한정이 적용된 T0*이며, T가 멤버 타입 T::first_argument_type을 가진 클래스 타입이라면 first_argument_type은 그 별칭이에요. |
second_argument_type (C++17에서 deprecated, C++20에서 제거) |
T가 두 인자 A1과 A2를 받는 함수 또는 함수 포인터라면 second_argument_type은 A2이고, T가 하나의 인자 A1을 받는 클래스 T0의 멤버 함수 포인터라면 second_argument_type은 cv 한정이 적용된 A1이며, T가 멤버 타입 T::second_argument_type을 가진 클래스 타입이라면 second_argument_type은 그 별칭이에요. |
멤버 함수
| 멤버 함수 | 설명 |
|---|---|
(constructor) |
새 std::reference_wrapper 객체에 참조를 저장해요. (public member function) |
operator= |
std::reference_wrapper를 다시 바인딩해요. (public member function) |
get, operator T& |
저장된 참조에 접근해요. (public member function) |
operator() |
저장된 함수를 호출해요. (public member function) |
비멤버 함수
| 함수 | 설명 |
|---|---|
operator==, operator<=> (C++26) |
저장된 참조로 reference_wrapper 객체를 비교해요. (function) |
추론 가이드 (C++17 이후)
C++17부터 std::reference_wrapper에 대한 추론 가이드가 제공돼요.
헬퍼 클래스
| 헬퍼 클래스 | 설명 |
|---|---|
std::basic_common_reference<std::reference_wrapper> (C++23) |
reference_wrapper와 비-reference_wrapper의 공통 참조 타입을 결정해요. (class template specialization) |
가능한 구현
namespace detail { template < class T > constexpr T & FUN ( T & t ) noexcept { return t ; } template < class T > void FUN ( T && ) = delete ; } template < class T > class reference_wrapper { public : // types using type = T ; // construct/copy/destroy template < class U , class = decltype ( detail :: FUN < T > ( std :: declval < U > ()), std :: enable_if_t <! std :: is_same_v < reference_wrapper , std :: 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 ; // assignment reference_wrapper & operator = ( const reference_wrapper & x ) noexcept = default ; // access 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 noexcept ( std :: is_nothrow_invocable_v < T & , ArgTypes ... > ) { return std :: invoke ( get (), std :: forward < ArgTypes > ( args )...); } private : T * _ptr ; }; // deduction guides template < class T > reference_wrapper ( T & ) -> reference_wrapper < T > ;
예제
std::reference_wrapper를 참조 컨테이너로 사용하는 예제를 보여줘요. 이렇게 하면 여러 인덱스로 동일한 컨테이너에 접근할 수 있어요.
#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
#include <numeric>
#include <random>
#include <vector>
void println(auto const rem, std::ranges::range auto const& v)
{
for (std::cout << rem; auto const& e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
std::list<int> l(10);
std::iota(l.begin(), l.end(), -4);
// can't use shuffle on a list (requires random access), but can use it on a vector
std::vector<std::reference_wrapper<int>> v(l.begin(), l.end());
std::ranges::shuffle(v, std::mt19937{std::random_device{}()});
println("Contents of the list: ", l);
println("Contents of the list, as seen through a shuffled vector: ", v);
std::cout << "Doubling the values in the initial list...\n";
std::ranges::for_each(l, [](int& i) { i *= 2; });
println("Contents of the list, as seen through a shuffled vector: ", v);
}
가능한 출력:
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
같이 보기
| 함수 | 설명 |
|---|---|
ref, cref (C++11) |
인자에서 타입을 추론한 std::reference_wrapper를 생성해요. (function template) |
bind (C++11) |
하나 이상의 인자를 함수 객체에 바인딩해요. (function template) |
unwrap_reference, unwrap_ref_decay (C++20) |
std::reference_wrapper에 감싸인 참조 타입을 가져와요. (class template) |