The following code triggers static_assert
even though I don't think it should:
#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()
{
}
When compiled with:
g++-4.9 -std=c++11 nothrow_destructible_bug.cc
The following happens:
nothrow_destructible_bug.cc:20:1: error: static assertion failed: That's odd
static_assert( std::is_nothrow_destructible< Foo >::value, "That's odd" );
^
How come just using Foo
to instantiate a template in an unrelated class make it lose its noexcept
status? I thought this was a compiler bug, but I tried it with all recent versions of both gcc and clang and they all seem to give the same error.
Where you use Tmp< Foo > xx
, Foo
is an incomplete type. This violates one of the preconditions for use of is_nothrow_destructible
, and its use is undefined behavior. One possibility of that UB is for is_nothrow_destructible
to be false.
Commenting out the use of Tmp will avoid that issue. Since the template is not instantiated until it is used, commenting out the constructor will also avoid the problem because the template won't yet be instantiated.
Moving the definition of the struct Foo
before Bar
should also avoid the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With