Topic: Attribute [[trivially_copyable]]
Author: Myriachan <myriachan@gmail.com>
Date: Wed, 13 Aug 2014 19:34:37 -0700 (PDT)
Raw View
------=_Part_3692_1228484260.1407983677591
Content-Type: text/plain; charset=UTF-8
I think that it would be nice if it were possible to declare that a type is
trivially-copyable despite what would ordinarily disqualify the type. In
other words, to force a type to be considered trivially-copyable even if
it, for example, has a user-defined copy constructor or user-defined
destructor. I propose that this would be enabled with attribute
[[trivially_copyable]]. The [[trivially_copyable]] attribute would be an
optimization like C's restrict keyword, in that it is placed at the
programmer's peril.
Two examples of where it might be useful:
#pragma pack(push, 1) // Microsoftism that's taken hold in GCC and Clang,
even outside of Windows
struct alignas(__m128i) ObjectID
{
union
{
struct
{
std::uint8_t m_type;
std::uint32_t m_originator;
std::uint16_t m_ttl;
std::uint8_t m_flags;
std::uint64_t m_uniqueID;
};
__m128i m_sse;
};
inline ObjectID(const ObjectID ©)
{
_mm_store_si128(&this->m_sse, _mm_load_si128(©.m_sse));
}
inline ObjectID &operator =(const ObjectID ©)
{
_mm_store_si128(&this->m_sse, _mm_load_si128(©.m_sse));
return *this;
}
};
#pragma pack(pop)
Second example:
struct alignas(2 * sizeof(std::uint64_t)) PaddedUint32
{
union
{
std::uint32_t m_u32;
struct
{
std::uint64_t m_u64_1;
std::uint64_t m_u64_2;
} m_pad;
};
inline PaddedUint32(const PaddedUint32 ©)
{
m_u32 = copy.m_u32;
}
inline PaddedUint32 &operator =(const PaddedUint32 ©) const
{
m_u32 = copy.m_u32;
}
};
The reason for [[trivially_copyable]] in these two scenarios is that these
copy constructors speed up the copying process, but if memcpy were used
instead, the class would still work. If, for example, a vector
implementation detected that the classes were trivially-copyable, then it
could reallocate its internal array somewhere else using memcpy rather than
calling the copy constructor each time. It may also allow the compiler to
optimize out some things.
Details:
1. Not allowed for classes using virtual inheritance somewhere in the
hierarchy here or upward. Don't really want to think of what nastiness
would be involved. =)
2. Only when it is possible to implement [[trivially_copyable]] is it
required to be supported. An implementation may be using a strange design
for polymorphic classes, and imposing this on them, thus forcing a
different implementation, is unreasonable. But imposing this on
implementations that *don't* have strange data layouts seems fine: memcpying
classes with virtual functions works fine on most compilers, so allow
[[trivially_copyable]] on them.
3. [[trivially_copyable]] would be required to be supported on all classes
meeting the definition of a "standard-layout type".
4. The attribute would be inherited by derived classes the normal way: a
derived class would be also be trivially-copyable if it does not introduce
something that prevents being trivially-copyable, unless, of course, the
derived class has a [[trivially_copyable]] attribute of its own.
5. [[trivially_copyable]] is used at the programmer's peril. It can cause
all kinds of bugs, especially use-after-free bugs (from pointers being
copied via memcpy rather than via a user-defined copy constructor) and
memory leaks (from user-defined destructors not being called).
6. std::is_trivially_copyable<T>::value would be true for any class T with
the [[trivially_copyable]] attribute.
7. It would be implementation-defined under which situations a compiler
uses the copy constructor, the move constructor, std::memcpy, std::memmove,
or inlined memcpy/memmove-like machine code, or similar to one of these, to
copy around objects of classes with the [[trivially_copyable]] attribute in
any given situation. The idea was that the copy/move constructors would be
called for single copies/moves, and that memcpy/memmove would be used for
multiple adjacent copies/moves, but this is not required.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3692_1228484260.1407983677591
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I think that it would be nice if it were possible to decla=
re that a type is trivially-copyable despite what would ordinarily disquali=
fy the type. In other words, to force a type to be considered trivial=
ly-copyable even if it, for example, has a user-defined copy constructor or=
user-defined destructor. I propose that this would be enabled with a=
ttribute <span style=3D"font-family: courier new,monospace;">[[trivially_co=
pyable]]</span>. The <span style=3D"font-family: courier new,monospac=
e;">[[trivially_copyable]]</span> attribute would be an optimization like C=
's <span style=3D"font-family: courier new,monospace;">restrict</span> keyw=
ord, in that it is placed at the programmer's peril.<br><br>Two examples of=
where it might be useful:<br><br><div class=3D"prettyprint" style=3D"backg=
round-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-s=
tyle: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #800;" class=
=3D"styled-by-prettify">#pragma</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> pack</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">push</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #066;" class=3D"styled-by-prettify">1</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color:=
#800;" class=3D"styled-by-prettify">// Microsoftism that's taken hold in G=
CC and Clang, even outside of Windows</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> alignas</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">__m128i</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">ObjectID</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">union</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br> std</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">uint8_t m_type</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br> =
std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">uint32_t m_orig=
inator</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; std</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">uint16_t m_ttl</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> std</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">uint8_t m_flags</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> =
std</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">u=
int64_t m_uniqueID</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br> __m128i m_sse</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">inline</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">ObjectID</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">ObjectID</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">c=
opy</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>  =
; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
_mm_store_si128</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(&</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">this</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">-></span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">m_sse</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _mm_load=
_si128</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(&am=
p;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">copy</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">m_sse</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">));</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">inline</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">ObjectID</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">operator</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D(</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Objec=
tID</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">copy</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> _mm_s=
tore_si128</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(&</span><span style=3D"color: #008;" class=3D"styled-by-prettify">this=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-></spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">m_sse</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> _mm_load_si128</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(&</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">copy</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">m_sse</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">));</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">*</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">this</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br> </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">#pragma</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> pack</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">pop</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span></div></code></div><br>Second example=
:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250=
, 250); border-color: rgb(187, 187, 187); border-style: solid; border-width=
: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">str=
uct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> aligna=
s</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #066;" class=3D"styled-by-prettify">2</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">sizeof</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">uint64_=
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">))</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">PaddedUint32</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">union</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br> st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">uint32_t m_u32</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br> &nbs=
p; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br> std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">uint64_t m_u64_1</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>  =
; std</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">uint64=
_t m_u64_2</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
; </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> m_pad</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>&=
nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">inline</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">PaddedUint=
32</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">PaddedUint32</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">copy</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br> m_u32 </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> copy</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">m_u32</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">inline</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">PaddedUint32</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&</span><span style=3D"color: #008;" class=3D"styled-by-prettify">o=
perator</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D(</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #606;" class=3D"styled-by-prettify">PaddedUint32</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">copy</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br> m_u32 </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> copy</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">m_u32</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></=
code></div><br><br>The reason for <span style=3D"font-family: courier new,m=
onospace;">[[trivially_copyable]]</span> in these two scenarios is that the=
se copy constructors speed up the copying process, but if <span style=3D"fo=
nt-family: courier new,monospace;">memcpy</span> were used instead, the cla=
ss would still work. If, for example, a <span style=3D"font-family: c=
ourier new,monospace;">vector</span> implementation detected that the class=
es were trivially-copyable, then it could reallocate its internal array som=
ewhere else using <span style=3D"font-family: courier new,monospace;">memcp=
y</span> rather than calling the copy constructor each time. It may a=
lso allow the compiler to optimize out some things.<br><br>Details:<br><br>=
1. Not allowed for classes using virtual inheritance somewhere in the hiera=
rchy here or upward. Don't really want to think of what nastiness wou=
ld be involved. =3D)<br>2. Only when it is possible to implement <span styl=
e=3D"font-family: courier new,monospace;">[[trivially_copyable]]</span> is =
it required to be supported. An implementation may be using a strange=
design for polymorphic classes, and imposing this on them, thus forcing a =
different implementation, is unreasonable. But imposing this on imple=
mentations that <i>don't</i> have strange data layouts seems fine: <span st=
yle=3D"font-family: courier new,monospace;">memcpy</span>ing classes with v=
irtual functions works fine on most compilers, so allow <span style=3D"font=
-family: courier new,monospace;">[[trivially_copyable]]</span> on them.<br>=
3. <span style=3D"font-family: courier new,monospace;">[[trivially_copyable=
]]</span> would be required to be supported on all classes meeting the defi=
nition of a "standard-layout type".<br>4. The attribute would be inherited =
by derived classes the normal way: a derived class would be also be trivial=
ly-copyable if it does not introduce something that prevents being triviall=
y-copyable, unless, of course, the derived class has a <span style=3D"font-=
family: courier new,monospace;">[[trivially_copyable]]</span> attribute of =
its own.<br>5. <span style=3D"font-family: courier new,monospace;">[[trivia=
lly_copyable]]</span> is used at the programmer's peril. It can cause=
all kinds of bugs, especially use-after-free bugs (from pointers being cop=
ied via <span style=3D"font-family: courier new,monospace;">memcpy</span> r=
ather than via a user-defined copy constructor) and memory leaks (from user=
-defined destructors not being called).<br>6. <span style=3D"font-family: c=
ourier new,monospace;">std::is_trivially_copyable<T>::value</span> wo=
uld be <span style=3D"font-family: courier new,monospace;">true</span> for =
any class <span style=3D"font-family: courier new,monospace;">T</span> with=
the <span style=3D"font-family: courier new,monospace;">[[trivially_copyab=
le]]</span> attribute.<br>7. It would be implementation-defined under which=
situations a compiler uses the copy constructor, the move constructor, <sp=
an style=3D"font-family: courier new,monospace;">std::memcpy</span>, <span =
style=3D"font-family: courier new,monospace;">std::memmove</span>, or inlin=
ed <span style=3D"font-family: courier new,monospace;">memcpy</span>/<span =
style=3D"font-family: courier new,monospace;">memmove</span>-like machine c=
ode, or similar to one of these, to copy around objects of classes with the=
[[trivially_copyable]] attribute in any given situation. The idea wa=
s that the copy/move constructors would be called for single copies/moves, =
and that <span style=3D"font-family: courier new,monospace;">memcpy</span>/=
<span style=3D"font-family: courier new,monospace;">memmove</span> would be=
used for multiple adjacent copies/moves, but this is not required.<br><br>=
Melissa<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3692_1228484260.1407983677591--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dribeas@gmail.com>
Date: Thu, 14 Aug 2014 10:51:35 -0400
Raw View
--001a113a75a292d1560500980a13
Content-Type: text/plain; charset=UTF-8
A different approach would be to provide a trait. Existing libraries
(EASTL, BSL) use a bitwise movable trait in implementations of vector to
speed up the move when the buffer grows. After the memcpy/memmove into the
new location the source object is not destroyed. This goes along with the
recent message by Howard Hinnant describing the 4 possible move operations
that include destructive moves: the libraries use the trait to perform a
destructive move.
One important difference with what you propose is that there are far more
types that are bit wise movable than trivially copyable, as the original
object is not destroyed it can be used with types that manage resources. As
with your proposal, the user is responsible for providing the trait only
when it won't affect the semantics (well, this is really undefined
behavior, but for types that don't hold internal references it "works" as
expected).
I am not sure from the language perspective what is better, a trait or an
attribute, although I have the feeling that the trait might be a better
option, as it can be defined for fundamental and POD types implicitly by
the compiler and I don't know how that would work for an attribute. Other
than that, the bitwise-movable approach is less dangerous than the
trivially-copyable in the sense that the opportunity for misrepresenting
the type with the trait is smaller and while it only provides the
opportunity for optimization on destructive moves (never
copies/non-destructive moves). Although it cannot help with your two usage
examples. It is related, not even close to equivalent.
David
On 13/08/2014, at 22:34, Myriachan <myriachan@gmail.com> wrote:
I think that it would be nice if it were possible to declare that a type is
trivially-copyable despite what would ordinarily disqualify the type. In
other words, to force a type to be considered trivially-copyable even if
it, for example, has a user-defined copy constructor or user-defined
destructor. I propose that this would be enabled with attribute
[[trivially_copyable]]. The [[trivially_copyable]] attribute would be an
optimization like C's restrict keyword, in that it is placed at the
programmer's peril.
Two examples of where it might be useful:
#pragma pack(push, 1) // Microsoftism that's taken hold in GCC and Clang,
even outside of Windows
struct alignas(__m128i) ObjectID
{
union
{
struct
{
std::uint8_t m_type;
std::uint32_t m_originator;
std::uint16_t m_ttl;
std::uint8_t m_flags;
std::uint64_t m_uniqueID;
};
__m128i m_sse;
};
inline ObjectID(const ObjectID ©)
{
_mm_store_si128(&this->m_sse, _mm_load_si128(©.m_sse));
}
inline ObjectID &operator =(const ObjectID ©)
{
_mm_store_si128(&this->m_sse, _mm_load_si128(©.m_sse));
return *this;
}
};
#pragma pack(pop)
Second example:
struct alignas(2 * sizeof(std::uint64_t)) PaddedUint32
{
union
{
std::uint32_t m_u32;
struct
{
std::uint64_t m_u64_1;
std::uint64_t m_u64_2;
} m_pad;
};
inline PaddedUint32(const PaddedUint32 ©)
{
m_u32 = copy.m_u32;
}
inline PaddedUint32 &operator =(const PaddedUint32 ©) const
{
m_u32 = copy.m_u32;
}
};
The reason for [[trivially_copyable]] in these two scenarios is that these
copy constructors speed up the copying process, but if memcpy were used
instead, the class would still work. If, for example, a vector
implementation detected that the classes were trivially-copyable, then it
could reallocate its internal array somewhere else using memcpy rather than
calling the copy constructor each time. It may also allow the compiler to
optimize out some things.
Details:
1. Not allowed for classes using virtual inheritance somewhere in the
hierarchy here or upward. Don't really want to think of what nastiness
would be involved. =)
2. Only when it is possible to implement [[trivially_copyable]] is it
required to be supported. An implementation may be using a strange design
for polymorphic classes, and imposing this on them, thus forcing a
different implementation, is unreasonable. But imposing this on
implementations that *don't* have strange data layouts seems fine: memcpying
classes with virtual functions works fine on most compilers, so allow
[[trivially_copyable]] on them.
3. [[trivially_copyable]] would be required to be supported on all classes
meeting the definition of a "standard-layout type".
4. The attribute would be inherited by derived classes the normal way: a
derived class would be also be trivially-copyable if it does not introduce
something that prevents being trivially-copyable, unless, of course, the
derived class has a [[trivially_copyable]] attribute of its own.
5. [[trivially_copyable]] is used at the programmer's peril. It can cause
all kinds of bugs, especially use-after-free bugs (from pointers being
copied via memcpy rather than via a user-defined copy constructor) and
memory leaks (from user-defined destructors not being called).
6. std::is_trivially_copyable<T>::value would be true for any class T with
the [[trivially_copyable]] attribute.
7. It would be implementation-defined under which situations a compiler
uses the copy constructor, the move constructor, std::memcpy, std::memmove,
or inlined memcpy/memmove-like machine code, or similar to one of these, to
copy around objects of classes with the [[trivially_copyable]] attribute in
any given situation. The idea was that the copy/move constructors would be
called for single copies/moves, and that memcpy/memmove would be used for
multiple adjacent copies/moves, but this is not required.
Melissa
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a113a75a292d1560500980a13
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div dir=3D"auto"><div>A different approach would be to pr=
ovide a trait. =C2=A0Existing libraries (EASTL, BSL) use a bitwise movable =
trait in implementations of vector to speed up the move when the buffer gro=
ws. After the memcpy/memmove into the new location the source object is not=
destroyed. This goes along with the recent message by Howard Hinnant descr=
ibing the 4 possible move operations that include destructive moves: the li=
braries use the trait to perform a destructive move.</div>
<div><br></div><div>One important difference with what you propose is that =
there are far more types that are bit wise movable than trivially copyable,=
as the original object is not destroyed it can be used with types that man=
age resources. As with your proposal, the user is responsible for providing=
the trait only when it won't affect the semantics (well, this is reall=
y undefined behavior, but for types that don't hold internal references=
it "works" as expected).</div>
<div><br>I am not sure from the language perspective what is better, a trai=
t or an attribute, although I have the feeling that the trait might be a be=
tter option, as it can be defined for fundamental and POD types implicitly =
by the compiler and I don't know how that would work for an attribute. =
Other than that, the bitwise-movable approach is less dangerous than the tr=
ivially-copyable in the sense that the opportunity for misrepresenting the =
type with the trait is smaller and while it only provides the opportunity f=
or optimization on destructive moves (never copies/non-destructive moves). =
Although it cannot help with your two usage examples. It is related, not ev=
en close to equivalent.</div>
<div><br></div><div>=C2=A0 =C2=A0 David</div><div><br>On 13/08/2014, at 22:=
34, Myriachan <<a href=3D"mailto:myriachan@gmail.com" target=3D"_blank">=
myriachan@gmail.com</a>> wrote:<br><br></div><blockquote type=3D"cite"><=
div><div dir=3D"ltr">
I think that it would be nice if it were possible to declare that a type is=
trivially-copyable despite what would ordinarily disqualify the type.=C2=
=A0 In other words, to force a type to be considered trivially-copyable eve=
n if it, for example, has a user-defined copy constructor or user-defined d=
estructor.=C2=A0 I propose that this would be enabled with attribute <span =
style=3D"font-family:courier new,monospace">[[trivially_copyable]]</span>.=
=C2=A0 The <span style=3D"font-family:courier new,monospace">[[trivially_co=
pyable]]</span> attribute would be an optimization like C's <span style=
=3D"font-family:courier new,monospace">restrict</span> keyword, in that it =
is placed at the programmer's peril.<br>
<br>Two examples of where it might be useful:<br><br><div style=3D"backgrou=
nd-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;=
border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#800=
">#pragma</span><span style=3D"color:#000"> pack</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">push</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#066">=
1</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> =C2=
=A0</span><span style=3D"color:#800">// Microsoftism that's taken hold =
in GCC and Clang, even outside of Windows</span><span style=3D"color:#000">=
<br>
</span><span style=3D"color:#008">struct</span><span style=3D"color:#000"> =
alignas</span><span style=3D"color:#660">(</span><span style=3D"color:#000"=
>__m128i</span><span style=3D"color:#660">)</span><span style=3D"color:#000=
"> </span><span style=3D"color:#606">ObjectID</span><span style=3D"color:#0=
00"><br>
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">union</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">struct</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span=
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 std</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#000">uint8_t m=
_type</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><=
br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#000">uint32_t m_originator</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">uint16_t m_ttl</span><span style=3D"color:#660">;=
</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#000">uint8_t m_flags</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#660">::</span><span s=
tyle=3D"color:#000">uint64_t m_uniqueID</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#660">};</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 __m128i m_sse</span>=
<span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#660">};</span><span style=3D"color:#000=
"><br>
<br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">inline</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#606">ObjectID</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">const</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#606">ObjectID</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">&</span><span st=
yle=3D"color:#000">copy</span><span style=3D"color:#660">)</span><span styl=
e=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _mm_store_si128</span><span style=
=3D"color:#660">(&</span><span style=3D"color:#008">this</span><span st=
yle=3D"color:#660">-></span><span style=3D"color:#000">m_sse</span><span=
style=3D"color:#660">,</span><span style=3D"color:#000"> _mm_load_si128</s=
pan><span style=3D"color:#660">(&</span><span style=3D"color:#000">copy=
</span><span style=3D"color:#660">.</span><span style=3D"color:#000">m_sse<=
/span><span style=3D"color:#660">));</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">inline</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#606">ObjectID</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">&</sp=
an><span style=3D"color:#008">operator</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">=3D(</span><span style=3D"color:#008">const=
</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Object=
ID</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
;</span><span style=3D"color:#000">copy</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 _mm_store_si128</span><span style=
=3D"color:#660">(&</span><span style=3D"color:#008">this</span><span st=
yle=3D"color:#660">-></span><span style=3D"color:#000">m_sse</span><span=
style=3D"color:#660">,</span><span style=3D"color:#000"> _mm_load_si128</s=
pan><span style=3D"color:#660">(&</span><span style=3D"color:#000">copy=
</span><span style=3D"color:#660">.</span><span style=3D"color:#000">m_sse<=
/span><span style=3D"color:#660">));</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">*</span><span=
style=3D"color:#008">this</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</=
span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">};</span><span style=3D"color:#000"><br><=
/span><span style=3D"color:#800">#pragma</span><span style=3D"color:#000"> =
pack</span><span style=3D"color:#660">(</span><span style=3D"color:#000">po=
p</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>
</span></div></code></div><br>Second example:<br><br><div style=3D"backgrou=
nd-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;=
border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#008=
">struct</span><span style=3D"color:#000"> alignas</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#066">2</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">*</span><span style=3D"color:#000"> =
</span><span style=3D"color:#008">sizeof</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">std</span><span style=3D"color:#660">::</=
span><span style=3D"color:#000">uint64_t</span><span style=3D"color:#660">)=
)</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Padde=
dUint32</span><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">union</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span sty=
le=3D"color:#660">::</span><span style=3D"color:#000">uint32_t m_u32</span>=
<span style=3D"color:#660">;</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">struct</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#660">::</span><spa=
n style=3D"color:#000">uint64_t m_u64_1</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#000">uint64_t m_u64_2</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000=
"> m_pad</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">};</span><span style=3D"col=
or:#000"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">inline</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#606">PaddedUint=
32</span><span style=3D"color:#660">(</span><span style=3D"color:#008">cons=
t</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Padde=
dUint32</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>&</span><span style=3D"color:#000">copy</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 m_u32 </span><span style=3D"color:#=
660">=3D</span><span style=3D"color:#000"> copy</span><span style=3D"color:=
#660">.</span><span style=3D"color:#000">m_u32</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">inline</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#606">PaddedUint3=
2</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
</span><span style=3D"color:#008">operator</span><span style=3D"color:#000"=
> </span><span style=3D"color:#660">=3D(</span><span style=3D"color:#008">c=
onst</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Pa=
ddedUint32</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">&</span><span style=3D"color:#000">copy</span><span style=3D"color:=
#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>const</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 m_u32 </span><span style=3D"color:#=
660">=3D</span><span style=3D"color:#000"> copy</span><span style=3D"color:=
#660">.</span><span style=3D"color:#000">m_u32</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#660">};</span><span style=3D"color=
:#000"><br></span></div></code></div><br><br>The reason for <span style=3D"=
font-family:courier new,monospace">[[trivially_copyable]]</span> in these t=
wo scenarios is that these copy constructors speed up the copying process, =
but if <span style=3D"font-family:courier new,monospace">memcpy</span> were=
used instead, the class would still work.=C2=A0 If, for example, a <span s=
tyle=3D"font-family:courier new,monospace">vector</span> implementation det=
ected that the classes were trivially-copyable, then it could reallocate it=
s internal array somewhere else using <span style=3D"font-family:courier ne=
w,monospace">memcpy</span> rather than calling the copy constructor each ti=
me.=C2=A0 It may also allow the compiler to optimize out some things.<br>
<br>Details:<br><br>1. Not allowed for classes using virtual inheritance so=
mewhere in the hierarchy here or upward.=C2=A0 Don't really want to thi=
nk of what nastiness would be involved. =3D)<br>2. Only when it is possible=
to implement <span style=3D"font-family:courier new,monospace">[[trivially=
_copyable]]</span> is it required to be supported.=C2=A0 An implementation =
may be using a strange design for polymorphic classes, and imposing this on=
them, thus forcing a different implementation, is unreasonable.=C2=A0 But =
imposing this on implementations that <i>don't</i> have strange data la=
youts seems fine: <span style=3D"font-family:courier new,monospace">memcpy<=
/span>ing classes with virtual functions works fine on most compilers, so a=
llow <span style=3D"font-family:courier new,monospace">[[trivially_copyable=
]]</span> on them.<br>
3. <span style=3D"font-family:courier new,monospace">[[trivially_copyable]]=
</span> would be required to be supported on all classes meeting the defini=
tion of a "standard-layout type".<br>4. The attribute would be in=
herited by derived classes the normal way: a derived class would be also be=
trivially-copyable if it does not introduce something that prevents being =
trivially-copyable, unless, of course, the derived class has a <span style=
=3D"font-family:courier new,monospace">[[trivially_copyable]]</span> attrib=
ute of its own.<br>
5. <span style=3D"font-family:courier new,monospace">[[trivially_copyable]]=
</span> is used at the programmer's peril.=C2=A0 It can cause all kinds=
of bugs, especially use-after-free bugs (from pointers being copied via <s=
pan style=3D"font-family:courier new,monospace">memcpy</span> rather than v=
ia a user-defined copy constructor) and memory leaks (from user-defined des=
tructors not being called).<br>
6. <span style=3D"font-family:courier new,monospace">std::is_trivially_copy=
able<T>::value</span> would be <span style=3D"font-family:courier new=
,monospace">true</span> for any class <span style=3D"font-family:courier ne=
w,monospace">T</span> with the <span style=3D"font-family:courier new,monos=
pace">[[trivially_copyable]]</span> attribute.<br>
7. It would be implementation-defined under which situations a compiler use=
s the copy constructor, the move constructor, <span style=3D"font-family:co=
urier new,monospace">std::memcpy</span>, <span style=3D"font-family:courier=
new,monospace">std::memmove</span>, or inlined <span style=3D"font-family:=
courier new,monospace">memcpy</span>/<span style=3D"font-family:courier new=
,monospace">memmove</span>-like machine code, or similar to one of these, t=
o copy around objects of classes with the [[trivially_copyable]] attribute =
in any given situation.=C2=A0 The idea was that the copy/move constructors =
would be called for single copies/moves, and that <span style=3D"font-famil=
y:courier new,monospace">memcpy</span>/<span style=3D"font-family:courier n=
ew,monospace">memmove</span> would be used for multiple adjacent copies/mov=
es, but this is not required.<br>
<br>Melissa<br></div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113a75a292d1560500980a13--
.
Author: Myriachan <myriachan@gmail.com>
Date: Thu, 14 Aug 2014 15:28:56 -0700 (PDT)
Raw View
------=_Part_41_1443060624.1408055336567
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, August 14, 2014 7:51:38 AM UTC-7, David Rodr=C3=ADguez Ibeas w=
rote:
>
> A different approach would be to provide a trait. Existing libraries=20
> (EASTL, BSL) use a bitwise movable trait in implementations of vector to=
=20
> speed up the move when the buffer grows. After the memcpy/memmove into th=
e=20
> new location the source object is not destroyed. This goes along with the=
=20
> recent message by Howard Hinnant describing the 4 possible move operation=
s=20
> that include destructive moves: the libraries use the trait to perform a=
=20
> destructive move.
>
> One important difference with what you propose is that there are far more=
=20
> types that are bit wise movable than trivially copyable, as the original=
=20
> object is not destroyed it can be used with types that manage resources. =
As=20
> with your proposal, the user is responsible for providing the trait only=
=20
> when it won't affect the semantics (well, this is really undefined=20
> behavior, but for types that don't hold internal references it "works" as=
=20
> expected).
>
> I am not sure from the language perspective what is better, a trait or an=
=20
> attribute, although I have the feeling that the trait might be a better=
=20
> option, as it can be defined for fundamental and POD types implicitly by=
=20
> the compiler and I don't know how that would work for an attribute. Other=
=20
> than that, the bitwise-movable approach is less dangerous than the=20
> trivially-copyable in the sense that the opportunity for misrepresenting=
=20
> the type with the trait is smaller and while it only provides the=20
> opportunity for optimization on destructive moves (never=20
> copies/non-destructive moves). Although it cannot help with your two usag=
e=20
> examples. It is related, not even close to equivalent.
>
> David
>
>
What do you mean by providing a trait instead? A template in <type_traits>=
=20
that can be specialized if one wants to mark their class as bitwise movable=
=20
or trivially-copyable? If that's what you mean, mine is a superset of a=20
trait: the attribute would trigger the std::is_trivially_copyable<T> flag,=
=20
presumably by having the compiler return true in whatever compiler=20
intrinsic.
Bitwise-movable would mean that a class can be moved using memcpy/memmove,=
=20
but only if the original object's destructor is never called? Or would the=
=20
destructor still be called on the original? I'm not the greatest at this=
=20
sort of move semantics yet; in the normal move case, I know the destructor=
=20
would be called.
Melissa
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_41_1443060624.1408055336567
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 14, 2014 7:51:38 AM UTC-7, David Rodr=
=C3=ADguez Ibeas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><div dir=3D"auto"><div>A different approach would be to provide a=
trait. Existing libraries (EASTL, BSL) use a bitwise movable trait i=
n implementations of vector to speed up the move when the buffer grows. Aft=
er the memcpy/memmove into the new location the source object is not destro=
yed. This goes along with the recent message by Howard Hinnant describing t=
he 4 possible move operations that include destructive moves: the libraries=
use the trait to perform a destructive move.</div>
<div><br></div><div>One important difference with what you propose is that =
there are far more types that are bit wise movable than trivially copyable,=
as the original object is not destroyed it can be used with types that man=
age resources. As with your proposal, the user is responsible for providing=
the trait only when it won't affect the semantics (well, this is really un=
defined behavior, but for types that don't hold internal references it "wor=
ks" as expected).</div>
<div><br>I am not sure from the language perspective what is better, a trai=
t or an attribute, although I have the feeling that the trait might be a be=
tter option, as it can be defined for fundamental and POD types implicitly =
by the compiler and I don't know how that would work for an attribute. Othe=
r than that, the bitwise-movable approach is less dangerous than the trivia=
lly-copyable in the sense that the opportunity for misrepresenting the type=
with the trait is smaller and while it only provides the opportunity for o=
ptimization on destructive moves (never copies/non-destructive moves). Alth=
ough it cannot help with your two usage examples. It is related, not even c=
lose to equivalent.</div>
<div><br></div><div> David</div><br></div></div></blockquote><=
div><br>What do you mean by providing a trait instead? A template in =
<span style=3D"font-family: courier new,monospace;"><type_traits></sp=
an> that can be specialized if one wants to mark their class as bitwise mov=
able or trivially-copyable? If that's what you mean, mine is a supers=
et of a trait: the attribute would trigger the <span style=3D"font-family: =
courier new,monospace;">std::is_trivially_copyable<T></span> flag, pr=
esumably by having the compiler return true in whatever compiler intrinsic.=
<br><br>Bitwise-movable would mean that a class can be moved using <span st=
yle=3D"font-family: courier new,monospace;">memcpy</span>/<span style=3D"fo=
nt-family: courier new,monospace;">memmove</span>, but only if the original=
object's destructor is never called? Or would the destructor still b=
e called on the original? I'm not the greatest at this sort of move s=
emantics yet; in the normal move case, I know the destructor would be calle=
d.<br><br>Melissa<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_41_1443060624.1408055336567--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 14 Aug 2014 18:36:50 -0700
Raw View
On Thursday 14 August 2014 15:28:56 Myriachan wrote:
> What do you mean by providing a trait instead? A template in <type_traits>
> that can be specialized if one wants to mark their class as bitwise movable
> or trivially-copyable? If that's what you mean, mine is a superset of a
> trait: the attribute would trigger the std::is_trivially_copyable<T> flag,
> presumably by having the compiler return true in whatever compiler
> intrinsic.
Besides the convenience, why should we do it by way of an attribute instead of
a specialisation?
We've done template specialisation in Qt for 9 years, with the help of a
macro. Our biggest problem is not the template specialisation, it's the macro.
See Q_DECLARE_TYPEINFO.
> Bitwise-movable would mean that a class can be moved using memcpy/memmove,
> but only if the original object's destructor is never called? Or would the
> destructor still be called on the original? I'm not the greatest at this
> sort of move semantics yet; in the normal move case, I know the destructor
> would be called.
Bitwise-movable means the type can be moved by memcpy, so long as the old
object isn't ever used again -- even the destructor must not be called on it.
This is useful for containers because they can simply memcpy a block of
objects (including via realloc) without the need to invoke individual copy or
move constructors.
Bitwise-copyable means a new instance of the type can be created by memcpy,
and both the old and the new objects can still be used and destroyed. This is
rare outside of trivial types. Most types that are bitwise-copyable will
probably also be trivially copyable and destructible. I don't see the need to
specify this trait.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Myriachan <myriachan@gmail.com>
Date: Thu, 14 Aug 2014 20:30:29 -0700 (PDT)
Raw View
------=_Part_156_579944521.1408073429966
Content-Type: text/plain; charset=UTF-8
On Thursday, August 14, 2014 6:36:57 PM UTC-7, Thiago Macieira wrote:
>
> On Thursday 14 August 2014 15:28:56 Myriachan wrote:
> > What do you mean by providing a trait instead? A template in
> <type_traits>
> > that can be specialized if one wants to mark their class as bitwise
> movable
> > or trivially-copyable? If that's what you mean, mine is a superset of a
> > trait: the attribute would trigger the std::is_trivially_copyable<T>
> flag,
> > presumably by having the compiler return true in whatever compiler
> > intrinsic.
>
> Besides the convenience, why should we do it by way of an attribute
> instead of
> a specialisation?
>
1. Because some STL implementations directly invoke the compiler intrinsics
behind the traits instead of using the traits. In other words,
specializing the trait templates has no effect.
2. Because compilers don't consult type traits template specializations
when deciding how to generate code for whatever it's doing.
We've done template specialisation in Qt for 9 years, with the help of a
> macro. Our biggest problem is not the template specialisation, it's the
> macro.
> See Q_DECLARE_TYPEINFO.
>
> > Bitwise-movable would mean that a class can be moved using
> memcpy/memmove,
> > but only if the original object's destructor is never called? Or would
> the
> > destructor still be called on the original? I'm not the greatest at
> this
> > sort of move semantics yet; in the normal move case, I know the
> destructor
> > would be called.
>
> Bitwise-movable means the type can be moved by memcpy, so long as the old
> object isn't ever used again -- even the destructor must not be called on
> it.
> This is useful for containers because they can simply memcpy a block of
> objects (including via realloc) without the need to invoke individual copy
> or
> move constructors.
>
Makes sense. I'd consider that equally worthy of what I'm suggesting -- it
could be an attribute, too. Actually, more worthy, since it happens more
often than bitwise-copyable.
> Bitwise-copyable means a new instance of the type can be created by
> memcpy,
> and both the old and the new objects can still be used and destroyed. This
> is
> rare outside of trivial types. Most types that are bitwise-copyable will
> probably also be trivially copyable and destructible. I don't see the need
> to
> specify this trait.
>
The problem is, not always. The ObjectID class example I started with --
which came from a real-world example -- results in the compiler being dumb
and emitting 8 "mov" instructions to copy a single ObjectID in 32-bit
builds. With the copy constructor, it becomes 2 "movdqa" instructions.
The problem is, merely giving the class a copy constructor suddenly causes
every container class to start treating the type differently, using slower
copy and move techniques. The compiler also stops eliding some unnecessary
copies.
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_156_579944521.1408073429966
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 14, 2014 6:36:57 PM UTC-7, Thiago Maci=
eira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thursday 14 Augu=
st 2014 15:28:56 Myriachan wrote:
<br>> What do you mean by providing a trait instead? A template in=
<type_traits>
<br>> that can be specialized if one wants to mark their class as bitwis=
e movable
<br>> or trivially-copyable? If that's what you mean, mine is a su=
perset of a
<br>> trait: the attribute would trigger the std::is_trivially_copyable&=
lt;T> flag,
<br>> presumably by having the compiler return true in whatever compiler
<br>> intrinsic.
<br>
<br>Besides the convenience, why should we do it by way of an attribute ins=
tead of=20
<br>a specialisation?
<br></blockquote><div><br>1. Because some STL implementations directly invo=
ke the compiler intrinsics behind the traits instead of using the traits.&n=
bsp; In other words, specializing the trait templates has no effect.<br>2. =
Because compilers don't consult type traits template specializations when d=
eciding how to generate code for whatever it's doing.<br><br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;">We've done template specialisation in =
Qt for 9 years, with the help of a=20
<br>macro. Our biggest problem is not the template specialisation, it's the=
macro.=20
<br>See Q_DECLARE_TYPEINFO.
<br>
<br>> Bitwise-movable would mean that a class can be moved using memcpy/=
memmove,
<br>> but only if the original object's destructor is never called? &nbs=
p;Or would the
<br>> destructor still be called on the original? I'm not the grea=
test at this
<br>> sort of move semantics yet; in the normal move case, I know the de=
structor
<br>> would be called.
<br>
<br>Bitwise-movable means the type can be moved by memcpy, so long as the o=
ld=20
<br>object isn't ever used again -- even the destructor must not be called =
on it.=20
<br>This is useful for containers because they can simply memcpy a block of=
=20
<br>objects (including via realloc) without the need to invoke individual c=
opy or=20
<br>move constructors.
<br></blockquote><div><br>Makes sense. I'd consider that equally wort=
hy of what I'm suggesting -- it could be an attribute, too. Actually,=
more worthy, since it happens more often than bitwise-copyable.<br> <=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">Bitwise-copyable means a =
new instance of the type can be created by memcpy,=20
<br>and both the old and the new objects can still be used and destroyed. T=
his is=20
<br>rare outside of trivial types. Most types that are bitwise-copyable wil=
l=20
<br>probably also be trivially copyable and destructible. I don't see the n=
eed to=20
<br>specify this trait.
<br></blockquote><div><br> The problem is, not always. The Objec=
tID class example I started with -- which came from a real-world example --=
results in the compiler being dumb and emitting 8 "mov" instructions to co=
py a single ObjectID in 32-bit builds. With the copy constructor, it =
becomes 2 "movdqa" instructions. The problem is, merely giving the cl=
ass a copy constructor suddenly causes every container class to start treat=
ing the type differently, using slower copy and move techniques. The =
compiler also stops eliding some unnecessary copies.<br><br>Melissa<br></di=
v></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_156_579944521.1408073429966--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 14 Aug 2014 23:34:35 -0700
Raw View
On Thursday 14 August 2014 20:30:29 Myriachan wrote:
> On Thursday, August 14, 2014 6:36:57 PM UTC-7, Thiago Macieira wrote:
> > On Thursday 14 August 2014 15:28:56 Myriachan wrote:
> > > What do you mean by providing a trait instead? A template in
> >
> > <type_traits>
> >
> > > that can be specialized if one wants to mark their class as bitwise
> >
> > movable
> >
> > > or trivially-copyable? If that's what you mean, mine is a superset of a
> > > trait: the attribute would trigger the std::is_trivially_copyable<T>
> >
> > flag,
> >
> > > presumably by having the compiler return true in whatever compiler
> > > intrinsic.
> >
> > Besides the convenience, why should we do it by way of an attribute
> > instead of
> > a specialisation?
>
> 1. Because some STL implementations directly invoke the compiler intrinsics
> behind the traits instead of using the traits. In other words,
> specializing the trait templates has no effect.
I don't see this as a problem.
First, we haven't agreed that the trait is is_trivially_copyable anyway. We're
talking about a bitwise *movable* concept, not the copyable one. We might need
a completely new trait here.
Second, anything using compiler intrinsics is shipped with the compiler, since
those intrinsics are not standardised and may change at any time. If the
compiler is updated to understand the new attribute, the compiler can also
update its implementation to use the specialisations properly.
> 2. Because compilers don't consult type traits template specializations
> when deciding how to generate code for whatever it's doing.
Why would a compiler need to generate anything here?
I understand the need for container types. What condition are you thinking of
here?
> > Bitwise-copyable means a new instance of the type can be created by
> > memcpy,
> > and both the old and the new objects can still be used and destroyed. This
> > is
> > rare outside of trivial types. Most types that are bitwise-copyable will
> > probably also be trivially copyable and destructible. I don't see the need
> > to
> > specify this trait.
>
> The problem is, not always. The ObjectID class example I started with --
> which came from a real-world example -- results in the compiler being dumb
> and emitting 8 "mov" instructions to copy a single ObjectID in 32-bit
> builds. With the copy constructor, it becomes 2 "movdqa" instructions.
> The problem is, merely giving the class a copy constructor suddenly causes
> every container class to start treating the type differently, using slower
> copy and move techniques. The compiler also stops eliding some unnecessary
> copies.
Please file a bug report against your compiler about missed optimisations.
If all of the copy constructors are inline, the compiler should be able to
realise that it's just doing a bitwise copy and coalesce into one 16-byte copy
instruction.
If the copy constructors are not inline, then I have to question whether the
type is really bitwise-copyable.
Though yes, a trait about bitwise-copyability would be nice for containers
when copying the container.
I think we need to answer this question first: is there any condition under
which template code could legitimately want to know that a type really has a
trivial copy or move constructor, as opposed to having a non-trivial one that
can be elided by a memcpy?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Fri, 15 Aug 2014 07:49:36 -0700 (PDT)
Raw View
------=_Part_579_37720758.1408114176255
Content-Type: text/plain; charset=UTF-8
On Friday, August 15, 2014 7:34:48 AM UTC+1, Thiago Macieira wrote:
>
> On Thursday 14 August 2014 20:30:29 Myriachan wrote:
> [snip]
> > 2. Because compilers don't consult type traits template specializations
> > when deciding how to generate code for whatever it's doing.
>
> Why would a compiler need to generate anything here?
>
>
in some ABIs, the trivially copiable types use different calling
conventions (for example can be passed and returned via registers). Being
able to declare a type to be trivially copiable even when it wouldn't
otherwise be would be a bit win. For example on GCC std::pair<int, int> is
trivially copiable, while std::tuple<int, int> isn't.
As it must be possible to determine whether a type is trivially copiable by
looking at the definition of the type itself, a proper language feature is
required (even an attribute might not be appropriate).
-- gpd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_579_37720758.1408114176255
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, August 15, 2014 7:34:48 AM UTC+1, Thiago Maciei=
ra wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thursday 14 August=
2014 20:30:29 Myriachan wrote:
<br>[snip]<br>> 2. Because compilers don't consult type traits template =
specializations
<br>> when deciding how to generate code for whatever it's doing.
<br>
<br>Why would a compiler need to generate anything here?
<br>
<br></blockquote><div><br>in some ABIs, the trivially copiable types use di=
fferent calling conventions (for example can be passed and returned via reg=
isters). Being able to declare a type to be trivially copiable even when it=
wouldn't otherwise be would be a bit win. For example on GCC std::pa=
ir<int, int> is trivially copiable, while std::tuple<int, int> =
isn't.<br><br>As it must be possible to determine whether a type is trivial=
ly copiable by looking at the definition of the type itself, a proper langu=
age feature is required (even an attribute might not be appropriate).<br><b=
r>-- gpd<br></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_579_37720758.1408114176255--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 15 Aug 2014 08:27:55 -0700
Raw View
On Friday 15 August 2014 07:49:36 Giovanni Piero Deretta wrote:
> On Friday, August 15, 2014 7:34:48 AM UTC+1, Thiago Macieira wrote:
> > On Thursday 14 August 2014 20:30:29 Myriachan wrote:
> > [snip]
> >
> > > 2. Because compilers don't consult type traits template specializations
> > > when deciding how to generate code for whatever it's doing.
> >
> > Why would a compiler need to generate anything here?
>
> in some ABIs, the trivially copiable types use different calling
> conventions (for example can be passed and returned via registers). Being
> able to declare a type to be trivially copiable even when it wouldn't
> otherwise be would be a bit win. For example on GCC std::pair<int, int> is
> trivially copiable, while std::tuple<int, int> isn't.
>
> As it must be possible to determine whether a type is trivially copiable by
> looking at the definition of the type itself, a proper language feature is
> required (even an attribute might not be appropriate).
This is now particularly dangerous.
I know there are attributes that can change the ABI, like [[gnu::packed]] or
[[gnu::regparm]] for functions, but those are not standardised by the
language.
If we add [[trivially_copyable]], I'd expect compilers not to use it to affect
the ABI, since people might add it to existing classes not knowing the effect
it might have.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 15 Aug 2014 09:47:44 -0700 (PDT)
Raw View
I'm replying from my iPad, so I don't have a way to quote, due to lack of f=
eatures in the mobile version of Google Groups.
Thiago, definitely yes it shouldn't affect the ABI on external-linkage func=
tions, as like you say, that's just asking for trouble.
However, it could be used for internal-linkage functions--if the compiler c=
an prove that no other translation unit can call a particular function, it =
can use whatever calling convention it wants, including passing these thing=
s in registers. This gets better with link-time code generation, where it =
can then use weird calling conventions for external-linkage functions that =
cross translation units but not ELF/PE boundaries (i.e. it won't do this to=
a function if anything asks for a pointer to that function).
All in all, that is still a performance win.
Melissa
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Fri, 15 Aug 2014 11:54:57 -0500
Raw View
--001a1134dac4f4dc690500ade3b4
Content-Type: text/plain; charset=UTF-8
On 15 August 2014 11:47, Myriachan <myriachan@gmail.com> wrote:
> However, it could be used for internal-linkage functions--if the compiler
> can prove that no other translation unit can call a particular function, it
> can use whatever calling convention it wants, including passing these
> things in registers.
>
If the compiler can prove that, why does it need the attribute?
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134dac4f4dc690500ade3b4
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 15 August 2014 11:47, Myriac=
han <span dir=3D"ltr"><<a href=3D"mailto:myriachan@gmail.com" target=3D"=
_blank">myriachan@gmail.com</a>></span> wrote:<br><div class=3D"gmail_qu=
ote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex">
<div id=3D":3br" class=3D"a3s" style=3D"overflow:hidden">However, it could =
be used for internal-linkage functions--if the compiler can prove that no o=
ther translation unit can call a particular function, it can use whatever c=
alling convention it wants, including passing these things in registers.</d=
iv>
</blockquote><div><br></div><div>If the compiler can prove that, why does i=
t need the attribute?</div></div>-- <br>=C2=A0Nevin ":-)" Liber=
=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blan=
k">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134dac4f4dc690500ade3b4--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 15 Aug 2014 12:51:09 -0700
Raw View
On Friday 15 August 2014 11:54:57 Nevin Liber wrote:
> On 15 August 2014 11:47, Myriachan <myriachan@gmail.com> wrote:
> > However, it could be used for internal-linkage functions--if the compiler
> > can prove that no other translation unit can call a particular function,
> > it
> > can use whatever calling convention it wants, including passing these
> > things in registers.
>
> If the compiler can prove that, why does it need the attribute?
Indeed.
The compiler would benefit from the attribute if the copy constructor were not
inline, but that's a extreme case. And even with inline ones, the compiler
might get lost though by the activities of the copy constructor, enough to
throw the compiler off.
To give an example, Qt's reference counted types are almost all bitwise-
movable. Some types have inline copy constructor, like QString, QByteArray and
the container types. Some others don't, since the reference counter is inside
the private-implementation structure (examples are QNetworkProxy, QJsonValue,
etc.). In either case, the compiler can't prove much since the reference
counting is either implemented in inline assembly or via std::atomic.
One thing I'd like to see in the future is to be able to tell the compiler
about the refcount semantics along with the memory model. A reference count of
1 will not change by actions of another thread.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.