2013-08-08 43 views
27

Tôi đang cố gắng hiểu std::reference_wrapper.Cách sử dụng đúng std :: reference_wrappers

Mã sau đây cho thấy trình bao bọc tham chiếu không hoạt động chính xác như tham chiếu.

#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; 
} 

Nếu tôi hiểu chính xác, chuyển đổi ẩn không áp dụng cho các chức năng thành viên đang gọi. Đây có phải là giới hạn vốn có không? Tôi có thường xuyên sử dụng số std::reference_wrapper::get không?

Một trường hợp khác là thế này:

#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; 
} 

này hoạt động tốt, nhưng khi tôi thêm này trên main định nghĩa:

template <typename T> 
bool operator < (T left, T right) 
{ 
    return left.someMember(); 
} 

Trình biên dịch cố gắng để nhanh chóng các mẫu và quên về chuyển đổi ngầm và toán tử tích hợp.

Hành vi này vốn có hay tôi hiểu nhầm điều gì đó quan trọng về số std::reference_wrapper?

+3

'std :: reference_wrapper' có một số sử dụng rất cụ thể cho các tác giả thư viện, có liên quan đến việc chuyển tiếp và lưu trữ đối số hoàn hảo (xem ví dụ:' std :: bind' và 'std :: thread'). Tôi không khuyên bạn nên sử dụng nó bên ngoài những tình huống đó. – Xeo

+8

'reference_wrapper' không thay thế cho tham chiếu. –

+2

'mẫu toán tử bool <(T trái, phải) { trả lại left.someMember(); } 'là một ví dụ về những gì không bao giờ EVER EVER EVER DO khi quá tải một toán tử. Bất kỳ vấn đề nào xảy ra do mã đó không phải là vấn đề của bất kỳ thứ gì khác trong cơ sở mã của bạn. (ok, có thể trong một số không gian bị hạn chế và kiểm soát 'không gian tên' được tìm thấy thông qua ADL, hoặc các tình huống tương tự khác) – Yakk

Trả lời

28

Lớp std::reference_wrapper<T> thực hiện một nhà điều hành ngầm chuyển sang T&:

operator T&() const noexcept; 

và một getter rõ ràng hơn:

T& get() const noexcept; 

Nhà điều hành ngầm được gọi khi một T (hoặc T&) là bắt buộc. Ví dụ

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. 

Tuy nhiên, đôi khi một T không nhất thiết mong đợi và, trong trường hợp này, bạn phải sử dụng get. Điều này xảy ra, chủ yếu, trong bối cảnh khấu trừ loại tự động. Ví dụ,

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> 

Để có được some_type thay vì std::reference_wrapper<some_type> trên, bạn nên làm

auto y = x.get(); // the type of y is some_type 
g(x.get());  // U = some_type 

Alternativelly dòng cuối cùng ở trên có thể được thay thế bằng g<some_type>(x);. Tuy nhiên, đối với các nhà khai thác templatized (ví dụ: ostream::operator <<()) Tôi tin rằng bạn không thể rõ ràng loại.

+0

nó không có vẻ rõ ràng: http: //en.cppreference.com/w/cpp/utility/functional/reference_wrapper/nhận được – xaxxon

+0

@xaxxon: Đó là lỗi đánh máy và ý tôi là "ẩn". Tôi đã sửa bài đăng. Cảm ơn. –

Các vấn đề liên quan