2015-04-20 21 views
16

Với chương trình sau đây:Có phải std :: abs (0u) không đúng định dạng?

#include <cmath> 

int main() 
{ 
    std::abs(0u) ; 
} 

gccclang không đồng ý về việc này là vô hình thành. Sử dụng gcc với libstdc++ mã được xây dựng mà không có lỗi hoặc cảnh báo (see it live), trong khi sử dụng clang với libc++ nó tạo được lỗi sau (see it live):

error: call to 'abs' is ambiguous 
std::abs(0u) ; 
^~~~~~~~ 

Mà kết quả là chính xác? Có nên abs(0u) không rõ ràng hay không?


Biến đổi chỉ ra một câu hỏi thú vị có liên quan: Template version of std::abs.

Trả lời

16

Có vẻ như libstdc++ là chính xác, đây không phải là hình thành không đúng, mặc dù chúng tôi sẽ thấy có một số nghi ngờ thể hiện liệu đây có phải là lỗi trong vấn đề hoạt động LWG 2192 hay không.

Dự thảo C++ 11 phần chuẩn 26.8[c.math] đoạn 11 nói:

Hơn nữa, có phải quá tải thêm đủ để đảm bảo:

và bao gồm các mặt hàng sau:

  1. Nếu không, nếu có argu ment tương ứng với một tham số kép có kiểu double hoặc một kiểu số nguyên, sau đó tất cả các đối số tương ứng với các tham số đôi được cast thành gấp đôi.

và chúng tôi libstdc++ này có thể thấy không indeed provide for this trường hợp:

template<typename _Tp> 
inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, 
                double>::__type 
abs(_Tp __x) 
{ return __builtin_fabs(__x); } 

Có một cũng là một báo cáo gcc lỗi std::abs (long long) resorts to std::abs (double) if llabs is absent, mà câu hỏi nếu thực hiện điều này là đúng và một phản ứng nói:

[...] là tốt cho mỗi tiêu chuẩn, bất kỳ số nguyên nào được cho là vô điều kiện trở thành dou ble. [...]

Báo cáo lỗi cuối cùng dẫn đến LWG active issue 2192: Validity and return type of std::abs(0u) is unclear được đệ mà nói giữa những thứ khác:

  1. Trong C++ 11 bổ sung "đủ quá tải" quy tắc từ 26,8 [c .math] P11 (xem thêm LWG 2086) có thể được đọc là áp dụng đối với std :: abs() quá tải là tốt, mà có thể dẫn đến khả năng kết luận sau:

Chương trình

#include <type_traits> 
    #include <cmath> 

    static_assert(std::is_same<decltype(std::abs(0u)), double>(), "Oops"); 

    int main() { 
     std::abs(0u); // Calls std::abs(double) 
    } 

bắt buộc phải được định dạng tốt, vì dấu đầu dòng 2 ("[..] hoặc loại số nguyên [..]") của 26,8 [c.math] p11 (Lưu ý rằng độ phân giải hiện tại là của LWG 2086 không khắc phục được sự cố này).

  1. Bất kỳ đơn vị dịch nào bao gồm cả hai và có thể bị hình thành do hai yêu cầu xung đột đối với loại trả về của quá tải std :: abs (int).

Dường như với tôi rằng ít nhất kết quả thứ hai không có ý định, Cá nhân tôi nghĩ rằng cả hai đều bất hạnh [...] Nó cũng nên lưu ý, rằng "kiểu hàm tổng quát" quy tắc đặt tương ứng từ C99/C1x trong 7,25 p2 + 3 bị giới hạn đối với các hàm dấu phẩy động từ và, do đó không thể áp dụng cho các hàm abs (nhưng đối với hàm fabs!).

Câu hỏi đặt ra là liệu điều này có được áp dụng cho abs không. Đây có thể là lỗi do dường như không có cách nào để diễn giải từ ngữ hiện tại để loại trừ abs.

Từ ngữ hiện tại cho biết libstdc++ phù hợp, không rõ tại sao libc++ đã chọn triển khai hiện tại của chúng. Tôi không thể tìm thấy báo cáo lỗi cũng như các cuộc thảo luận liên quan đến chủ đề này và vấn đề LWG không đề cập đến việc triển khai phân tách.

Các giải pháp đề xuất sẽ làm cho std::abs(0u) vô hình thành:

Nếu abs() được gọi với một đối số kiểu không thể thiếu unsigned mà không thể được chuyển đổi sang int bởi chương trình khuyến mãi không thể thiếu ([conv.prom]) , chương trình bị lỗi. [Lưu ý: đối số có thể được thăng chức int được phép để tương thích với C. - cuối note]

Trong khi một số có thể đặt câu hỏi về quan điểm của việc sử dụng abs với một kiểu unsigned Howard Hinnant chỉ ra trong báo cáo rằng khi việc sử dụng các mẫu hậu quả như vậy có thể không rõ ràng và cung cấp ví dụ:

[...] đặc biệt là trong C++ nơi chúng tôi có mẫu và không phải lúc nào cũng rõ ràng với lập trình viên. Ví dụ, xem xét:

template <class Int> 
Int 
analyze(Int x, Int y) 
{ 
    // ... 
    if (std::abs(x - y) < threshold) 
    { 
    // ... 
    } 
    // ... 
} 
+0

[2192 đã được chuyển đến một khiếm khuyết] (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2192) –

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