xem xét mảnh này của C++ 11 mã:Thu hẹp chuyển đổi đến bool trong danh sách-khởi tạo - hành vi kỳ lạ
#include <iostream>
struct X
{
X(bool arg) { std::cout << arg << '\n'; }
};
int main()
{
double d = 7.0;
X x{d};
}
Có một chuyển đổi thu hẹp từ một đôi để một bool trong việc khởi tạo x
. Theo sự hiểu biết của tôi về tiêu chuẩn, đây là mã hình thành không đúng và chúng ta sẽ thấy một số chẩn đoán.
Visual C++ 2013 phát hành một lỗi:
error C2398: Element '1': conversion from 'double' to 'bool' requires a narrowing conversion
Tuy nhiên, cả Clang 3.5.0 và GCC 4.9.1, sử dụng các tùy chọn sau
-Wall -Wextra -std=c++11 -pedantic
biên dịch mã này với không có lỗi và không có cảnh báo. Chạy chương trình kết quả đầu ra là 1
(không có bất ngờ ở đó).
Bây giờ, hãy đi sâu hơn vào lãnh thổ xa lạ.
Thay đổi X(bool arg)
-X(int arg)
và, đột nhiên, chúng tôi đã có một lỗi từ Clang
error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
và một cảnh báo từ GCC
warning: narrowing conversion of 'd' from 'double' to 'int' inside { } [-Wnarrowing]
này trông giống như những gì tôi mong đợi.
Bây giờ, giữ lập luận constructor bool
(nghĩa là, trở lại X(bool arg)
), và thay đổi double d = 7.0;
để int d = 7;
. Một lần nữa, một lỗi thu hẹp từ Clang, nhưng GCC không đưa ra bất kỳ chẩn đoán nào và biên dịch mã.
Có một vài biến thể hành vi khác mà chúng ta có thể nhận được nếu chúng ta chuyển trực tiếp liên tục đến hàm tạo, một số lạ, một số được mong đợi, nhưng tôi sẽ không liệt kê chúng ở đây - câu hỏi này sẽ mất quá nhiều thời gian.
tôi muốn nói đây là một trong những trường hợp hiếm hoi khi VC++ là đúng và Clang và GCC là sai khi nói đến tiêu chuẩn phù hợp, nhưng, do các hồ sơ theo dõi tương ứng của các trình biên dịch, tôi vẫn còn rất do dự về điều này.
Các chuyên gia nghĩ gì?
tài liệu tham khảo Tiêu chuẩn (trích dẫn từ các tài liệu chuẩn cuối cùng cho C++ 11, ISO/IEC 14.882-2.011):
Trong 8.5.4 [dcl.init.list] đoạn 3, chúng tôi có:
— Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.
trong phần tương tự, tại khoản 7, ta có:
A narrowing conversion is an implicit conversion
— from a floating-point type to an integer type, or
— from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly), or
— from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or
— from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type.
[ Note: As indicated above, such conversions are not allowed at the top level in list-initializations.—end note ]
trong 3.9.1 [cơ bản.cơ bản] đoạn 7, ta có:
Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types.48 A synonym for integral type is integer type.
(tôi đã bắt đầu đặt câu hỏi về tất cả mọi thứ ở giai đoạn này ...)
Hey, nơi mà tất cả những ý kiến đi? Một số người trong số họ chứa thông tin hữu ích để chẩn đoán vấn đề, đặc biệt đối với Clang. – bogdan
Một số nhận xét đó sẽ rất hữu ích để gửi báo cáo lỗi, tôi không hiểu tại sao tất cả chúng bị xóa, có thể yêu cầu [meta] (http://meta.stackoverflow.com/) có thể hữu ích, tôi không không có thời gian. Bạn cũng có thể thử cờ tùy chỉnh nhưng bạn không biết nó sẽ hoạt động bao lâu trước khi nó được thực hiện. –
@dyp không chắc chắn bạn sẽ thấy điều này vì nhận xét của bạn đã bị xóa nhưng các liên kết hữu ích của bạn với mã nguồn của tiếng kêu vang đã bị xóa và sẽ hữu ích khi đưa chúng trở lại. –