2015-10-06 25 views
5

Các mã sau đây gây nên static_assert mặc dù tôi không nghĩ rằng nó nên:hành vi kỳ lạ của std :: is_nothrow_destructible

#include <type_traits> 

template< typename T > 
struct Tmp 
{ 
    ~Tmp() noexcept(std::is_nothrow_destructible<T>::value) {} 
}; 

struct Foo; 

struct Bar 
{ 
    // Comment this out for the problem to go away 
    Tmp<Foo> xx; 

    // ..or this 
    Bar() {} 
}; 

struct Foo {}; 

// This triggers 
static_assert(std::is_nothrow_destructible<Foo>::value, "That's odd"); 

int main() 
{ 
} 

Khi biên soạn với:

g++-4.9 -std=c++11 nothrow_destructible_bug.cc 

Sau đây sẽ xảy ra:

nothrow_destructible_bug.cc:20:1: error: static assertion failed: That's odd 
static_assert(std::is_nothrow_destructible<Foo>::value, "That's odd"); 
^ 

Cách chỉ sử dụng Foo để tạo mẫu trong một lớp học không liên quan làm cho nó mất tình trạng noexcept của nó? Tôi nghĩ rằng đây là một lỗi trình biên dịch, nhưng tôi đã thử nó với tất cả các phiên bản gần đây của cả gcc và clang và tất cả họ dường như cung cấp cho cùng một lỗi.

+0

Ý của bạn là kiểm tra 'is_nothrow_destructible < Bar >' thay vì 'is_nothrow_destructible < Foo >'? –

Trả lời

4

Nơi bạn sử dụng Tmp<Foo> xx, Foo là loại không đầy đủ. Điều này vi phạm một trong các điều kiện tiên quyết để sử dụng is_nothrow_destructible và việc sử dụng nó là hành vi không xác định. Một khả năng của UB là is_nothrow_destructible là sai.

Nhận xét việc sử dụng Tmp sẽ tránh được vấn đề đó. Vì khuôn mẫu không được khởi tạo cho đến khi nó được sử dụng, việc nhận xét ra constructor cũng sẽ tránh được vấn đề bởi vì khuôn mẫu sẽ chưa được khởi tạo.

Di chuyển định nghĩa của struct Foo trước Bar cũng nên tránh sự cố.

+0

"is_nothrow_destructable [sic] sẽ là sai." Nó đơn giản là UB. Chuyện gì cũng có thể xảy ra. –

+0

Tôi tự hỏi những điều kiện đó là gì và nơi tôi có thể đọc về chúng? Thực tế là có một UB im lặng trong trường hợp này làm tôi sợ – dragonroot

+0

@dragonroot Chúng đều nằm trong tài liệu chuẩn ngôn ngữ. Nếu tài liệu của bạn cho is_nothrow_destructible không đề cập đến loại cần phải là một loại hoàn chỉnh, bạn nên gửi một báo cáo lỗi cho nó. – 1201ProgramAlarm