Subject: Re: [Boost-bugs] [Boost C++ Libraries] #11835: boost::has_trivial_copy is incorrect on Clang
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-12-13 12:03:32
#11835: boost::has_trivial_copy is incorrect on Clang
-------------------------+-------------------------------------------------
Reporter: | Owner: johnmaddock
joseph.thomson@⦠| Status: closed
Type: Bugs | Component: type_traits
Milestone: To Be | Severity: Problem
Determined | Keywords: has_trivial_copy clang memcpy
Version: Boost | is_trivially_copyable
1.59.0 |
Resolution: wontfix |
-------------------------+-------------------------------------------------
Comment (by johnmaddock):
> has_trivial_copy and its related traits do not adhere to your
definition of "trivial" on some compilers.
I just checked them all with gcc 4.6.4, 4.7.4, 4.8.4, 4.9.2, 5.1.0, plus
clang and Intel and they all do the correct thing - which is to say they
all regard deleted operators as non-trivial. This is in 1.60 beta BTW.
Also verified our tests check this. Note that all these traits have been
completely rewritten for the next release.
> The documentation for these traits says that they can be used to check
whether memcpy is safe to use; this is incorrect, as is_trivially_copyable
is the required condition.
We have never provided is_trivially_copyable, if we did it would likely be
composed from these traits. Plus I believe you have this backwards -
is_trivially_copy_constructible is the std trait - and there is a
precondition on that trait that the type be copy-constructible, from
C++14:
"For a referenceable type T, the same result as
is_trivially_constructible<T, const T&>::value, otherwise false."
and then is_trivially_constructible says:
"is_constructible<T, Args...>::value is true and the variable definition
for is_constructible, as defined below, is known to call no operation that
is not trivial ( 3.9, 12)."
Which would rule out types with deleted copy-constructors from being
trivially-copyable.
> Your preferred definition of "trivial" is too conservative, and will
result in some obviously memcpy-able types reporting false for
is_trivially_copyable.
Such as? Note that has_trivial_copy (which I accept is badly named)
refers only to copy-constructors. In your example:
{{{
struct X
{
const int val;
};
}}}
If you care at all about const-correctness (and you should) then such a
type really is non-trivial, or more specifically:
{{{
default construct trivial
copy-construct trivial
move-construct trivial
destruct trivial
copy-assign not trivial or allowed
move-assign not trivial or allowed
}}}
Which I believe is what 1.60 has implemented.
> The current standard definition of is_trivially_copyable is potentially
dangerous when types use certain OS-level resources; a pending amendment
to the standard fixes this.
Right, IMO code should use traits which pertain to the actual operation
that will be performed - for example boost::has_trivial_copy is closest to
std::is_trivially_copy_constructible and both should return false for non-
copyable types and avoid that nasty (and very real) black hole.
One final point: has_trivial_copy and friends were developed for C++03
(and later included in TR1 standard). There's a lot of code out there
which relies on has_trivial_copy implies safe-to-memcpy instead of copy
construct. That code should absolutely not be broken just because C++11
has introduced new features: ie deleted functions.
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/11835#comment:6> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:19 UTC