User account creation filtered due to spam.

Bug 71788 - is_trivially_copy_constructible gives false for types with user defined destructors
Summary: is_trivially_copy_constructible gives false for types with user defined destr...
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 5.3.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-07 04:09 UTC by bplusplus
Modified: 2016-07-07 10:20 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description bplusplus 2016-07-07 04:09:06 UTC
Given the type

struct Tp
{
    Tp() = default;
    Tp(const Tp&) = default;
    Tp(Tp&&) = default;
    ~Tp() {}
};

The following static asserts fail

static_assert(std::is_trivially_copy_constructible<Tp>::value, "");
static_assert(std::is_trivially_move_constructible<Tp>::value, "");

If the destructor is defaulted (or removed, such that it is implicitly generated), the asserts do not trigger.

I'm not entirely sure this is a bug, but as far as I can determine from the standard, it is. Relevant text (ยง12.8 [class.copy], paragraph 12):

"A copy/move constructor for class X is trivial if it is not user-provided, its parameter-type-list is equivalent to the parameter-type-list of an implicit declaration, and if
- class X has no virtual functions (10.3) and no virtual base classes (10.1), and
- class X has no non-static data members of volatile-qualified type, and
- the constructor selected to copy/move each direct base class subobject is trivial, and
- for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial;

otherwise the copy/move constructor is non-trivial."

No mention that a user defined destructor should make either copy or move constructors non-trivial if they otherwise qualify. Additionally, using the old std::has_trivial_copy_constructor (and the built-in __has_trivial_copy it's based on) does not trigger the assert.
Comment 1 Jonathan Wakely 2016-07-07 10:20:44 UTC
Your non-trivial destructor means that is_trivially_xxx_constructible is false, because that trait is based on an expression that creates and destroys an object.

That's by design, because simply asking whether the type *has* a trivial constructor doesn't actually help, in typical generic code you want to know if a particular operation is trivial.