2015-10-06 3 views
5

Следующий код вызывает static_assert хотя я не думаю, что он должен:Странное поведение станд :: 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() 
{ 
} 

при компиляции:

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

происходит следующее:

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

Почему просто использование Foo для создания шаблона в несвязанном классе заставляют его потерять свой статус noexcept? Я думал, что это ошибка компилятора, но я попробовал ее со всеми последними версиями как gcc, так и clang, и все они, похоже, дают ту же ошибку.

+0

Возможно, вы имели в виду 'is_nothrow_destructible < Bar >' вместо 'is_nothrow_destructible < Foo >'? –

ответ

4

Где вы используете Tmp<Foo> xx, Foo является неполным типом. Это нарушает одно из предварительных условий использования is_nothrow_destructible, а его использование - неопределенное поведение. Одна из возможностей этого UB для is_nothrow_destructible будет ложной.

Замечание использования Tmp позволит избежать этой проблемы. Поскольку шаблон не создается до его использования, комментирование конструктора также позволит избежать проблемы, потому что шаблон еще не будет создан.

Перемещение определения struct Foo до Bar также должно быть устранено.

+0

"is_nothrow_destructable [sic] будет ложным". Это просто UB. Все может случиться. –

+0

Интересно, что это за условия и где я могу прочитать о них? Тот факт, что в этом случае есть тихий UB, пугает меня – dragonroot

+0

@dragonroot Они все в стандартном документе языка. Если в вашей документации для is_nothrow_destructible не упоминается, что тип должен быть полным типом, вы должны представить для него отчет о дефекте. – 1201ProgramAlarm

Смежные вопросы