std::is_trivially_copyable
is still not supported in either of those two compilers (at least as far as gcc 4.6). But both provide __has_trivial_copy
directives that do pretty good job.
Except when it comes to deleted copy constructors.
struct A { A(A const&) =delete; };
__has_trivial_copy(A)
returns 1 in clang and 0 in gcc.
I was digging in the standard and could not find a clause that says whether the class is still considered trivially copyable when the copy constructor is deleted.
Who's right?
My inclination is to believe that gcc is right, because struct A
is not copyable at all, let alone trivially copyable. Also, there's a wide-spread consensus, that a deleted copy constructor can be seen as a privately declared, but not defined constructor, in which case gcc would still be right.
On the other hand, the standard in section 9/6 describes trivial-copyability in terms of not having any non-trivial operations. I guess if you read the standard as written, clang may be right.
libc++, clang's native library, supports std::is_trivially_copyable<T>
and, indeed, pretends on your example that the type is trivially copyable although it is clearly not trivially copyable. I think, 12.8 [class.copy] paragraph 12 defines the deleted constructor as non-trivial:
A copy/move constructor for class X is trivial if it is not user-provided ...
The deleted declaration is clearly user-provided. When I say "clearly" here I mean that I can't immediately back it up by the standard that declaring a function as deleted counts as user-provided...
Further investigation reveals that 8.4.2 [dcl.fct.def.default] paragraph 4 (thanks to Jesse Good for providing the reference) makes a deleted function non-user-provided:
... A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. ...
Thus, a class with a deleted copy constructor is indeed trivially copyable if there is no other reason to make non-trivially copyable (but none of those applies to the type A
in the question. That's a bit weird: type type cannot be copied using its copy constructor but it can be copied using std::memcpy()
! I'm not sure if this is really intentional.
Neither is correct or incorrect, since both are using extensions.
Warning: This answer was based on words which were in C++11 draft N3242, but are not in the final Standard. So it's not especially good. Leaving it up for comparison and discussion.
For what it seems you meant to ask: std::is_trivially_copyable<A>::value
(and also std::is_trivially_copy_constructible<A>::value
) must be false
.
12.8 paragraph 13:
A copy/move constructor for class
X
is trivial if it is neither user-provided nor deleted and if....
And just to be complete,
9 paragraph 6:
A trivially copyable class is a class that:
- has no non-trivial copy constructors (12.8),
- has no non-trivial move constructors (12.8),
- has no non-trivial copy assignment operators (13.5.3, 12.8),
- has no non-trivial move assignment operators (13.5.3, 12.8), and
- has a trivial destructor (12.4).
3.9 paragraph 9:
Scalar types, trivially copyable class types (Clause 9), arrays of such types, and cv-qualified versions of these types (3.9.3) are collectively called trivially copyable types.
20.9.4.3 Table 49:
Template:
template <class T> struct is_trivially_copyable;
Condition:
T
is a trivially copyable type (3.9)
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