2017-05-03 23 views
5

Tôi muốn viết một hàm foo rằng nên gọi operator() của tham số của nó, như minh họa trong (bị hỏng) mã bên dưới:Chuyển tiếp const-ness của thông số mẫu, tôi có nên sử dụng tham chiếu chuyển tiếp không?

template <typename T> void foo(const T& x){ 
    x(); 
} 

struct MyFunctor{ 
    int data; 
    void operator()(){ 
     /* stuff that might modify the data */ 
    } 
}; 

int main() 
{ 
    foo(MyFunctor{}); 
} 

Rõ ràng mã không hoạt động, vì operator() là phi const, nhưng foo() yêu cầu tham số của nó là const.

Là chức năng mẫu, foo() phải hoạt động với cả hai đối tượng const và không phải là const và không phải là cầu nối về đối số của nó.

Nếu tôi thay đổi foo() bằng cách loại bỏ các const như sau:

template <typename T> void foo(T& x) { /* ... */ } 

... nó cũng sẽ không làm việc vì bạn không thể chuyển đổi một tài liệu tham khảo rvalue đến một const tài liệu tham khảo không vế trái, vì vậy Không thể gọi số foo(MyFunctor{}).

Thay đổi foo() đến một tham chiếu giao nhận giải quyết tất cả các vấn đề:

template <typename T> void foo(T&& x) { /* ... */ } 

Nhưng đây là "đúng" cách? Tham chiếu chuyển tiếp không nên chỉ được sử dụng với std::forward() (tức là thông số không được xúc động ngoài việc chuyển tiếp tham chiếu đến chức năng khác)?

+2

Bạn có thể muốn đọc [Tham khảo chung trong C++ 11 — Scott Meyers] (https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers). Nó chứa một số giải thích sâu về việc sử dụng 'T && x'. – VTT

+0

Điều này là hoàn toàn tốt IMO –

+0

Tôi vinh dự có những người có danh tiếng sáu chữ số trả lời câu hỏi của tôi! – Bernard

Trả lời

3

Vâng, một tham chiếu giao nhận là đúng cách, và nếu nó giúp bạn bình tĩnh, bạn chắc chắn có thể chuyển tiếp các thông số:

template <typename T> void foo(T&& x){ 
    std::forward<T>(x)(); 
} 

Bây giờ nó thậm chí làm việc với các nhà khai thác cuộc gọi ref-đủ điều kiện.

+1

Nhà điều hành cuộc gọi đủ điều kiện là điều mới mà bạn đã dạy tôi hôm nay. – Bernard

0

Có, đây là toàn bộ mục đích của tham chiếu chuyển tiếp.

tham số không nên chạm ngoài chuyển nó đến một chức năng

Đó là chính xác những gì bạn đang làm.

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