2014-11-07 14 views
20

Tôi có đoạn như sau:Tại sao hoán đổi các mảng đa chiều không phải là ngoại lệ?

#include <algorithm> 
#include <iostream> 

int main(int argc, char** argv) { 
    int x[2][3]; 
    int y[2][3]; 

    using std::swap; 
    std::cout << noexcept(swap(x, y)) << "\n"; 

    return 0; 
} 

Sử dụng GCC 4.9.0, đây in 0. Tôi không hiểu tại sao.

Theo tiêu chuẩn có hai quá tải cho std::swap:

namespace std { 
    template<class T> void swap(T& a, T& b) noexcept(
     is_nothrow_move_constructible<T>::value && 
     is_nothrow_move_assignable<T>::value 
    ); 

    template<class T, size_t N> 
    void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))); 
} 

Trong sự hiểu biết của tôi noexcept specifier cho mảng nên làm việc một cách đệ quy cho mảng đa chiều.

Tại sao hoán đổi các mảng đa chiều không phải là noexcept?


Trong khi cố gắng tìm một ví dụ rất nhỏ mà vẫn cư xử kì lạ tôi đã đưa ra như sau:

#include <iostream> 

template<class T> struct Specialized  : std::false_type {}; 
template<>  struct Specialized<int> : std::true_type {}; 

template<class T>    void f(T& a) noexcept(Specialized<T>::value); 
template<class T, std::size_t N> void f(T (&a)[N]) noexcept(noexcept(f(*a))); 

int main(int argc, char** argv) { 
    int x, y[1], z[1][1]; 

    std::cout << noexcept(f(x)) << " " 
       << noexcept(f(y)) << " " 
       << noexcept(f(z)) << "\n"; 
} 

Sử dụng GCC 4.9.0 này in 1 1 0, nhưng một lần nữa tôi không hiểu tại sao.

+1

[clang say 1] (http://coliru.stacked-crooked.com/a/9d1c1e7307dda039) –

+0

Có vẻ rất lạ với tôi. Tôi đã tìm thấy [DR 809] (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809) [xuất hiện] (https://gcc.gnu.org/ onlinedocs/gcc-4.9.0/libstdC++/api/a01316_source.html # l00185) được [triển khai] (https://gcc.gnu.org/onlinedocs/libstdc++/manual/bugs.html) trong libstdC++ do đó có thể lỗi nằm ở nơi khác. Mỗi lần chỉnh sửa mới nhất của bạn, [clang] (http://coliru.stacked-crooked.com/a/79dd288d30d8f159) cũng in '1 1 0'. clang với libC++ in '0' cho đoạn mã gốc. –

+0

[Coliru] (http://coliru.stacked-crooked.com/a/7fa0b200e56d1bd4), [2] (http://coliru.stacked-crooked.com/a/485e10b802dd3a96) –

Trả lời

11

quá tải này:

template<class T, size_t N> 
void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b))); 

không nằm trong phạm vi cho đến khi ;, vì vậy swap(*a, *b) không xem xét tình trạng quá tải này. Điều này là vì:

3.3.2/1 Điểm kê khai cho một tên là ngay sau khi declarator hoàn chỉnh của nó (khoản 8) và trước khi khởi tạo của nó (nếu có) ...

và đặc tả ngoại lệ là một phần của người khai báo.

+3

Điều này có vẻ là một sự giám sát khá nghiêm trọng trong tiêu chuẩn. Trong hình thức hiện tại của nó ngây thơ ngây thơ 'noexcept' khai báo không hoạt động. Tệ hơn nữa, bản thân tiêu chuẩn sử dụng những khai báo đệ quy ngây thơ này. – orlp

+5

Nói với ông già Noel; anh ta sẽ đặt Bjarne vào danh sách nghịch ngợm. – rightfold

+0

Đây là lỗi đã biết. Xem [LWG2456] (http://wg21.cmeerw.net/lwg/issue2456). – FrankHB

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