Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
282 views
in Technique[技术] by (71.8m points)

c++ - Non-trivial destructor make class non-trivially-constructible

Consider following code:

#include <type_traits>

struct T {};

static_assert(std::is_trivially_destructible< T >{});
static_assert(std::is_trivially_default_constructible< T >{});

struct N { ~N() { ; } };

static_assert(!std::is_trivially_destructible< N >{});
static_assert(!std::is_trivially_default_constructible< N >{});

It compiles fine using clang 3.7.0: live example. But summarizing the Standard:

The default constructor for class T is trivial (i.e. performs no action) if all of the following is true:

  • The constructor is not user-provided (i.e., is implicitly-defined or defaulted)
  • T has no virtual member functions
  • T has no virtual base classes
  • T has no non-static members with default initializers. (since C++11)
  • Every direct base of T has a trivial default constructor
  • Every non-static member of class type has a trivial default constructor

As I can see there is no dependence on triviality of the destructor.

I missed something? Is it clang bug?

ADDITIONAL

I found a workaround: is static_assert(__has_trivial_constructor( N )); built-in type trait. There is support in clang, gcc and MSVC.

For is_noexcept_constructible family of type traits there is workaround too.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This issue is covered in LWG issue 2116: std::swap noexcept(what?), we can see this from the cppreference section for std::is_trivially_default_constructible:

In many implementations, is_nothrow_default_constructible also checks if the destructor throws because it is effectively noexept(T()): GCC bug 51452 LWG issue 2116

which deceptively only talks about is_nothrow_default_constructible but if we read the issue in detail we see it also applies here as well.

Perhaps is is easier if we follow the gcc bug report: [DR 2116] has_nothrow_.*constructor bugs referenced first which says:

The traits that detect nothrow constructibility are buggy because they are influenced by whether the object has a nothrow dtor; destruction is invoked at the end of evaluation of the full expression in the noexcept( ... ) operator. They all use the pattern of constructing a temporary inside noexcept, whereas they should be using placement new

this explicitly says what is only really alluded to in the LWG issue which eventually says:

is_nothrow_constructible is defined in terms of is_constructible, which is defined by looking at a hypothetical variable and asking whether the variable definition is known not to throw exceptions. The issue claims that this also examines the type's destructor, given the context, and thus will return false if the destructor can potentially throw. At least one implementation (Howard's) does return false if the constructor is noexcept(true) and the destructor is noexcept(false). So that's not a strained interpretation. The issue is asking for this to be defined in terms of placement new, instead of in terms of a temporary object, to make it clearer that is_nothrow_constructible looks at the noexcept status of only the constructor, and not the destructor.

which also effects std::is_trivially_default_constructible which relies on std::is_trivially_constructible which does the same as is_constructible but has the further restriction that:

but the variable definition does not call any operation that is not trivial


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...