2017-10-01 29 views
5

Chương trình này có được xuất ra 0 hoặc 1 không? Trong bài đọc và hiểu biết về các đoạn trích dẫn từ các tiêu chuẩn C++ 14 của tôi, nó nên in 1, nhưng cả hai GCC và kêu vang in 0 (vì kiểu suy luận là A const thay vì A const&):Toán tử điều kiện có cùng loại lớp cơ bản

#include <iostream> 

struct A {}; 

int main() 
{ 
    A a; 
    A const& ra = std::move(a); // #1 

    std::cout << std::is_same<decltype(true ? ra : std::move(a)), 
           A const&>::value; // Prints 0 
} 

trong này trường hợp, ra là một giá trị A conststd::move(a) là giá trị A xvalue, cả hai loại lớp. Theo tiêu chuẩn về các nhà điều hành có điều kiện (tôi nhấn mạnh), kết quả phải là một lvalue loại A const, và do đó các kết quả decltype phải A const&:

[expr.cond]/3 Ngược lại, nếu toán hạng thứ hai và thứ ba có các loại khác nhau và hoặc có (có thể là đủ điều kiện cv) lớp loại hoặc nếu cả hai đều là giá trị của cùng một danh mục giá trị và cùng loại ngoại trừ cv-qualification, thì thực hiện để chuyển đổi mỗi toán hạng đó cho loại khác. Quá trình xác định dù một biểu thức toán hạng E1 loại T1 có thể được chuyển đổi để phù hợp với một biểu thức toán hạng E2 loại T2 được định nghĩa như sau:

- Nếu E2 là một giá trị trái: E1 có thể được chuyển đổi để phù hợp với E2 nếu E1 có thể được chuyển đổi hoàn toàn (khoản 4) thành loại "tham chiếu lvalue đến T2", tùy thuộc vào ràng buộc trong chuyển đổi, tham chiếu phải liên kết trực tiếp (8.5.3) với giá trị.

[...]

Trong trường hợp này, E2ra, đó là một giá trị trái, và người kia có thể được chuyển đổi sang implicitely "tài liệu tham khảo giá trị trái để T2", như thể hiện trong dòng // #1. "tài liệu tham khảo giá trị trái để T2" được dịch là A const&, vì vậy, std::move(a) liên kết trực tiếp đến một vế trái của loại A const, và sau khi chuyển đổi, cả hai toán hạng có cùng loại và loại giá trị, và do đó:

[ expr.cond]/3 Nếu toán hạng thứ hai và thứ ba là các giá trị của cùng một danh mục giá trị và có cùng loại, kết quả là loại danh mục và giá trị đó [...].

Vì vậy, kết quả điều hành phải là một giá trị trái và decltype kết quả phải là một tài liệu tham khảo, và do đó chương trình sẽ in 1.

+0

điều này có thể ảnh hưởng đến hành vi của 'std :: common_type', không? hoặc ít nhất, việc triển khai mặc định: http://en.cppreference.com/w/cpp/types/common_type –

+0

@ChrisBeck Trong trường hợp cụ thể này không vì các tham số mẫu đầu tiên bị phân rã. –

+0

@ Peregring-lk Bạn nên ** không bao giờ ** sửa đổi một câu hỏi theo cách có thể làm mất hiệu lực nhận xét của người khác (hoặc câu trả lời). – Phil1970

Trả lời

6

Câu hỏi đặt ra là ngượng nghịu diễn đạt. Thay vào đó, bạn nên hỏi loại thể loại và giá trị của biểu thức true ? ra : std::move(a). Câu trả lời cho câu hỏi đó là giá trị của loại A const. Điều này sau đó có nghĩa là chương trình nên in 0, như tôi nghĩ mọi trình biên dịch đều đúng.


Quy tắc cho ?: khá phức tạp.Trong trường hợp này, chúng tôi có hai biểu thức của loại lớp mà chúng tôi cố gắng xem liệu chúng tôi có thể chuyển đổi với nhau hay không, dựa trên tập hợp con các quy tắc giới hạn.

Cố gắng chuyển đổi rastd::move(a) không thành công. Trước tiên, chúng tôi thử với một số target typeA&& không thể liên kết trực tiếp với ra. Sau đó chúng tôi thử kế hoạch sao lưu trong (3.3.1) vì hai biểu thức có cùng loại lớp cơ bản, nhưng biểu thức mục tiêu của chúng tôi không ít nhất là cv đủ điều kiện làm biểu thức nguồn, vì vậy điều này cũng không thành công.

Cố gắng chuyển đổi std::move(a)ra không (3.1) vì chúng ta cần phải liên kết trực tiếp đến một giá trị trái (chúng ta có thể ràng buộc một rvalue đến một tài liệu tham khảo giá trị trái const, nhưng ở đây chúng tôi đang cần để ràng buộc một giá trị trái). Tuy nhiên, sao lưu (3.3.1) thành công vì bây giờ loại mục tiêu ít nhất là cv đủ điều kiện làm nguồn.

Do đó, chúng tôi áp dụng chuyển đổi và tiếp tục như toán hạng thứ hai là loại giá trị A const nhưng toán hạng ba hiện là giá trị loại A const (thay vì xvalue loại A).

(4) không thành công, vì chúng không thuộc cùng một loại giá trị.

Do đó, result is a prvalue. Và vì chúng có cùng loại, the result is of that type: A const.

+0

@Barry Các quy tắc của "ràng buộc với giá trị" là gì? Chương về liên kết "tham chiếu" nói về "tài liệu tham khảo". Ý nghĩa của "ràng buộc trực tiếp với một lvalue" là gì? Tôi hiểu tất cả các bước ngoại trừ một bước, đó là một trong những thay đổi tất cả mọi thứ. –

+0

@ M.M Tốt, đã chỉnh sửa. – Barry

+0

@ Peregring-lk Tôi không hiểu câu hỏi. Từ ngữ có một yêu cầu mà chúng tôi liên kết với một giá trị, nhưng toán hạng khác của chúng tôi không phải là một giá trị - đó là một xvalue - vì vậy chúng tôi không thể làm điều đó. – Barry

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