2014-09-18 18 views
10

Tại sao static_assert cần nằm ngoài định nghĩa lớp?static_assert định nghĩa lớp bên trong/bên ngoài

Không đang

#include <type_traits> 

class A 
{ 
public: 
    A(A&&) noexcept {} 
    static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR"); 
}; 

int main() 
{ 
} 

đang làm việc

#include <type_traits> 

class A 
{ 
public: 
    A(A&&) noexcept {} 

}; 

static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR"); 

int main() 
{ 
} 

Và khi là nó thích hợp để sử dụng static_asserts trong định nghĩa của một lớp hoặc struct?

+0

Điều gì không hiệu quả với thiết bị đầu tiên? Có thông báo lỗi không? – 0x499602D2

+0

Tôi đã chỉnh sửa tiêu đề câu hỏi để phù hợp với nội dung câu hỏi. – aschepler

+0

@ 0x499602D2 Mã lỗi cung cấp thông báo này khi được biên soạn với g ++ --std = C++ 11 {code} is_nothrow_move_constructible.cpp: 8: 1: lỗi: xác nhận tĩnh không thành công: ERROR static_assert (std :: is_nothrow_move_constructible :: giá trị, "L ERI"); {code} – Parkesy

Trả lời

17

Theo như vị trí của static_assert, bản thân cả hai phiên bản mã của bạn đều hợp lệ. Vì vậy, không, static_assert không cần phải nằm ngoài định nghĩa lớp. Chính thức static_assert là khai báo . Nó được cho phép bất cứ nơi nào khai báo được cho phép.

Sự cố bạn đang gặp phải không liên quan gì với chính mình static_assert.

Vấn đề ở đây là biểu thức bạn sử dụng làm đối số của static_assert (std::is_nothrow_move_constructible) yêu cầu loại lớp là hoàn thành để hoạt động bình thường. Nhưng bên trong định nghĩa của lớp A loại lớp A chưa hoàn thành, điều này làm cho biểu thức đối số của bạn không hợp lệ. Đây là lý do tại sao công cụ static_assert của bạn hoạt động như dự định chỉ bên ngoài định nghĩa lớp, trong đó A hoàn tất. Tuy nhiên, điều này hoàn toàn về cách sử dụng hợp lý của std::is_nothrow_move_constructible, không phải về chính bản thân số static_assert.

Lưu ý rằng bên trong thành phần chức năng của lớp thành phần được xem toàn bộ, là kiểu hoàn chỉnh, ngay cả khi hàm thành viên được định nghĩa bên trong định nghĩa lớp. Sử dụng tính năng này, bạn có thể viết lại mã của mình dưới dạng

class A 
{ 
public: 
    A(A&&) noexcept { 
     static_assert(std::is_nothrow_move_constructible<A>::value, "ERROR"); 
    } 
}; 

std::is_nothrow_move_constructible<A> sẽ tạo ra kết quả phù hợp.

+0

Và, AFAIK, 'static_assert' có thể * được sử dụng bên trong phần thân của hàm * –

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