2013-01-31 33 views
15

Hãy xem xét các chương trình C++ sauthay đổi Breaking trong C++ 11 với make_pair (_Ty1 && _Val1, const _Ty2 & _Val2)

#include<map> 
#include<iostream> 
int main() { 
    int a = 5, b = 7; 
    auto pair = std::make_pair<int, int>(a,b); 
    return 0; 
    } 

Sử dụng VC11 và cũng trong gcc-4.7.2 fails với các lỗi khác nhau, mặc dù có vẻ như là có liên quan và VC11 thông báo lỗi là có ý nghĩa hơn

You cannot bind an lvalue to an rvalue 

Những gì tôi hiểu từ thất bại này

  1. VC11 và tôi supp là ose gcc-4.7.2 chỉ thực hiện một lệnh std :: make_pair make_pair(_Ty1&& _Val1, const _Ty2& _Val2) chỉ có thể chấp nhận tham chiếu rvalue. Trước khi VC++ phiên bản ví dụ VC10 có hai phiên bản, một để chấp nhận một giá trị trái và một tài liệu tham khảo một rvalue
  2. rvalue tài liệu tham khảo không thể được sử dụng để khởi tạo một tham chiếu const phi nghĩa int & a = b * 5 không hợp lệ.
  3. tôi có thể đã sử dụng std::move để chuyển đổi lvalue-rvalue tài liệu tham khảo và các cuộc gọi sẽ thành công.
  4. Như std::make_pair chấp nhận hai loại khác nhau cho mỗi người trong số các thông số, Mẫu Đối số Nghị quyết trong mọi trường hợp có thể có thể giải quyết các loại tham số và một cách rõ ràng xác định kiểu là không cần thiết.

Kịch bản này có vẻ tầm thường và không tương thích có thể dễ dàng được giải quyết bằng cách loại bỏ các loại đặc tả rõ ràng và đưa ra định nghĩa như

auto pair = std::make_pair(a,b); 
  • Bây giờ, câu hỏi của tôi là, yếu tố lái xe để loại bỏ là những gì việc thực hiện lvalue từ thư viện?
  • Có thể biết bất kỳ chức năng thư viện khác mà đã được thay đổi theo những cách tương tự?
  • Làm thế nào để xử lý các tình huống khi tôi cần phải nhắm mục tiêu nhiều trình biên dịch như g ++, CC, ACC, XL C++ nơi một trong hai trình biên dịch chưa được nâng cấp hoặc trình biên dịch không hỗ trợ các tài liệu tham khảo rvalue và hay di chuyển ngữ nghĩa.
+2

Vâng, nó không phải là một thay đổi phá vỡ, bởi vì những người trên trái đất sử dụng 'std :: make_pair' với instantiation mẫu rõ ràng? Nó được thiết kế rõ ràng * để thu lợi nhuận từ khấu trừ loại tự động. Vì vậy, vì hiếm khi ai cũng viết 'std :: make_pair ' để ủng hộ 'std :: make_pair', không có nhiều mã bị phá vỡ. Vâng, tốt đẹp, mặc dù. –

+1

Thật không may, tôi đã gặp phải mã nơi loại rõ ràng đã được chỉ định. – Abhijit

+0

Tôi tin rằng đây là vấn đề tương tự được thảo luận tại [http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43785](http://gcc.gnu.org/bugzilla/show_bug.cgi? id = 43785) – Nevin

Trả lời

19

std::make_pair tồn tại với mục đích duy nhất là khai thác loại khấu trừ để tránh nhập tên của các loại. Đó là lý do tại sao chỉ có một tình trạng quá tải (và nó sẽ mất hai universal references, không phải là một tài liệu tham khảo phổ thông và một tài liệu tham khảo giá trị trái để const như VC dường như nghĩ).

template <class T1, class T2> 
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y); 

Nếu bạn muốn gõ các loại một cách rõ ràng, bạn chỉ có thể sử dụng các nhà xây dựng cặp. Nó thậm chí còn ngắn hơn ...

auto pair = std::pair<int, int>(a,b); 
+0

Cảm ơn bạn đã trả lời. Tôi hiểu thực tế trên mặc dù là một cách khó khăn. Btw, bạn có thể giải thích 'tham chiếu phổ quát 'có nghĩa là gì? Thuật ngữ này mới đối với tôi. Ngoài ra, bạn còn có bất kỳ chức năng thư viện nào khác đã được thay đổi tương tự không? – Abhijit

+0

@Abhijit Tôi đã thêm một liên kết đến lời giải thích của Scott Meyer (anh ấy đã đưa ra thuật ngữ). Bất kỳ chức năng thư viện nào khác phục vụ cùng một mục đích (khai thác loại khấu trừ) có khả năng không hoạt động nếu bạn không sử dụng khấu trừ loại. Chúng thường có dạng 'make_something', như' make_tuple'. Vấn đề là họ không làm việc với các loại rõ ràng bởi vì chúng không hữu ích với các loại rõ ràng. –

+1

@Abhijit Để rõ ràng, "tham chiếu toàn cầu" chỉ là một thuật ngữ thông tục. Chúng thực sự chỉ là các tham chiếu rvalue, nhưng vì việc loại bỏ kiểu mẫu và các quy tắc thu gọn tham chiếu, chúng có một thuộc tính thú vị - đôi khi chúng hoạt động như tham chiếu lvalue và các thời điểm khác như tham chiếu rvalue. Nghĩ lại thì, chúng ta nên gọi đây là nhị nguyên * lvalue-rvalue *. –

18

Khi bạn làm std::make_pair<int, int>, bạn đang buộc các đối số mẫu T1T2 để cả hai được rút ra như int. Điều này cung cấp cho bạn chức năng như std::pair<int,int> make_pair(int&&, int&&). Bây giờ các đối số này chỉ có thể nhận giá trị bởi vì chúng là các tham chiếu rvalue.

Tuy nhiên, khi các loại T1T2 đang được suy ra bằng cách khấu trừ loại mẫu, chúng hoạt động như "tham chiếu chung". Đó là, nếu họ nhận được một đối số lvalue họ sẽ được tham chiếu lvalue và nếu họ nhận được một đối số rvalue họ sẽ được tham khảo rvalue.Điều này mang lại cho make_pair khả năng chuyển tiếp hoàn hảo.

Vì vậy, vấn đề là, không đưa ra các đối số loại mẫu một cách rõ ràng. Toàn bộ điểm của make_pair là nó tự suy ra các loại. Nếu bạn đặt tên các loại, nó không thể thực hiện chuyển tiếp hoàn hảo nữa và sẽ thất bại đối với các đối số lvalue.

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