Topic: I think many methods could be written by
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 23 Jan 2014 18:20:42 -0800
Raw View
On quinta-feira, 23 de janeiro de 2014 17:45:55, euloanty@live.com wrote:
> f& operator=(f&& bmv) noexcept
> {
> if(this!=&bmv)
> {
> fp=bmv.fp;
> bmv.fp=nullptr;
> }
> }
[snip]
> > When I write those operations, I often make mistakes to do these things,
You did here. Your move assignment operator leaks.
Your destructor has a problem too: fclose() is not required to operate on null
pointers.
[And your indentation has a problem too...]
> I think this code could be replaced as
[snip]
> //move operations defined
> f(f&& bmv) noexcept =auto;
> f& operator=(f&&) noexcept =auto;
We already have = default, but that won't do for your type. The default move
is to move each member and all of the bases. For pointers, the move is the
same as copying, which doesn't do what you wanted and would leak.
If you had used std::unique_ptr instead of a naked pointer, the default move
constructor and assignment operator would have worked.
So far, I don't see a good reason to change the language if you can just use
the proper classes instead.
> Of course. this replace has its conditions.
> It needs all its members are "auto-moved".
>
> You may say: why you think this will bring efficiency?
>
> You know we will have concept. So containers could find this type is
> "auto-moved", they can directly use memcpy,memmove to optimize it.
> And many no need operations could be optimized.
Types matching std::is_trivially_move_assignable and
std::is_trivially_move_constructible are memcpy'able for moving, since that's
what the compiler is generating in those trivial functions.
Of course, certain types might have non-trivial move assignment operators and
move constructors, yet still be memcpy'able, but there's no way for the
compiler to know that. That would be a library thing, not a language thing.
And this is the case here: your type is not trivially movable by the
compiler's definition of it. But it is memcpy'able from one location in memory
to another, provided the destructor is not called on the original location.
There's no trait for that.
In Qt, we have a trait for that: Q_MOVABLE_TYPE. You have to declare yourself
whether the type is movable or not, since it depends on how you construct it.
Like I said, it's a library issue.
> 2.
> swap can be automatic generated too.
Indeed, but before we go there, we need to define an operator for swapping (I
think the suggested was operator:=:). I really don't think letting the
compiler have to understand arbitrary function name is a good idea.
> 3.
> +,-,*,/ ....They can all auto generated +=,-=,*=,/=
> i++.
What is the compiler going to do on operator+= or operator++? Please suggest
what the compiler should do in an arbitrary class like the following, based on
the base classes and members:
struct X : public Base1, public Base2
{
Member1 m1;
Member2 m2;
};
--
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: Richard Smith <richard@metafoo.co.uk>
Date: Thu, 23 Jan 2014 19:59:26 -0800
Raw View
--047d7bf0d6c25084b904f0af62d3
Content-Type: text/plain; charset=ISO-8859-1
On Thu, Jan 23, 2014 at 5:45 PM, <euloanty@live.com> wrote:
> 1.move operations
>
> In C++11 we introduced move operations. But in fact move operations could
> be faster, for its meaning is almost move.
>
> #include<cstdio>
> class f
> {
> std::FILE *fp;
> public:
> std::FILE* get(){return fp;}
> f(const char *p):fp(std::fopen(p,"w")){}
> //copy operations deleted
> f(const f&)=delete;
> f& operator=(const f&)=delete;
>
> //move operations defined
>
> f(f&& bmv) noexcept : fp(bmv.fp)
> {
> bmv.fp=nullptr;
> }
> f& operator=(f&& bmv) noexcept
> {
> if(this!=&bmv)
> {
> fp=bmv.fp;
> bmv.fp=nullptr;
> }
> }
>
> ~f(){fclose(fp);}
> };
>
You can express this much more succinctly (and correctly!) as:
struct fcloser {
void operator()(std::FILE *fp) const { if (fp) fclose(fp); };
};
typedef std::unique_ptr<std::FILE*, fcloser> f;
> int main()
> {
> f a("324.txt");
> return 0;
> }
>
>
> But I think move operations are stupid, for the codes are very similar
> between different uses.
> When I write those operations, I often make mistakes to do these things,
> and it's difficult to change and maintain.
>
> I think this code could be replaced as
>
> #include<cstdio>
> class f
> {
> std::FILE *fp;
> public:
> std::FILE* get(){return fp;}
> f(const char *p):fp(std::fopen(p,"w")){}
> //copy operations deleted
> f(const f&)=delete;
> f& operator=(const f&)=delete;
>
> //move operations defined
> f(f&& bmv) noexcept =auto;
> f& operator=(f&&) noexcept =auto;
>
> ~f(){fclose(fp);}
> };
>
> int main()
> {
> f a("324.txt");
> return 0;
> }
>
>
> Of course. this replace has its conditions.
> It needs all its members are "auto-moved".
>
> You may say: why you think this will bring efficiency?
>
> You know we will have concept. So containers could find this type is
> "auto-moved", they can directly use memcpy,memmove to optimize it.
> And many no need operations could be optimized.
>
This can be, and is, already done. The standard already has something like
"auto-moved": is_trivially_move_constructible and
is_trivially_move_assignable. However, your above type does *not* qualify,
because the move operation can't simply use memcpy and memmove -- they must
also zero out the original pointer, and (for the move assignment) release
the destination pointer before clobbering it.
Adding the ability to detect the case where memcpy is equivalent to
move-construct-and-destroy-original might be interesting, but it's not
immediately obvious to me what safety guarantees would be necessary to
ensure that. (Essentially, we'd want to determine that the moved-from state
is in some sense trivially-destructible.)
> std::vector<f> vec;
> vec.emplace_back("32.txt"):
> When it do such things, it could directly called memcpy, and former
> resources could directly be destory, and I don't need to do the following
> sentenses:
> 1. if(this!=&bmv)
> 2. bmv.fp=nullptr;
> 3. allocator.deconstruct(*this);
> 4. allocator.destory(this,1);
>
> I just need to do:
> 1. memcpy(,,);
> 2. allocator.destory(vec.data(),vec.size());
>
> This will be very very fast.
>
Do you have benchmarks? Have you determined whether compilers will already
optimize the code down to the same thing?
> 2.
> swap can be automatic generated too.
>
This has been proposed here before.
> 3.
> +,-,*,/ ....They can all auto generated +=,-=,*=,/=
> i++.
> Those operations could make class types closer to internal types
>
This part hasn't been, but the response to such proposals in the past has
often been "let's get a reflection mechanism and implement this using that".
I assume you mean to implement + and ++ in terms of a user-provided +=, and
so on? FWIW, that can already be done with reasonably-elegant syntax via
CRTP.
--
---
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/.
--047d7bf0d6c25084b904f0af62d3
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Jan 23, 2014 at 5:45 PM, <span dir=3D"ltr"><<a href=3D"mailto:euloa=
nty@live.com" target=3D"_blank">euloanty@live.com</a>></span> wrote:<br>=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><p>1.move operations</p><p>In C++11 we introduced move ope=
rations. But in fact move operations could be faster, for its meaning is al=
most move.</p><p>#include<cstdio><br>class f<br>{<br>=A0std::FILE *fp=
;<br>
public:<br>=A0std::FILE* get(){return fp;}<br>=A0f(const char *p):fp(std::f=
open(p,"w")){}<br>//copy operations deleted<br>=A0f(const f&)=
=3Ddelete;<br>=A0f& operator=3D(const f&)=3Ddelete;</p><p>//move op=
erations defined </p>
<p>=A0f(f&& bmv) noexcept : fp(bmv.fp)<br>=A0{<br>=A0 bmv.fp=3Dnull=
ptr;<br>=A0}<br>=A0f& operator=3D(f&& bmv) noexcept<br>=A0{<br>=
=A0 if(this!=3D&bmv)<br>=A0 {<br>=A0=A0 fp=3Dbmv.fp;<br>=A0=A0 bmv.fp=
=3Dnullptr;<br>=A0 }<br>=A0}<br>=A0<br>
=A0~f(){fclose(fp);}<br>};</p></div></blockquote><div>You can express this =
much more succinctly (and correctly!) as:</div><div><br></div><div>struct f=
closer {</div><div>=A0 void operator()(std::FILE *fp) const { if (fp) fclos=
e(fp); };</div>
<div>};</div><div>typedef std::unique_ptr<std::FILE*, fcloser> f;</di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><p>int main()<br>{<br>=A0=
f a("324.txt");<br>
=A0return 0;<br>}</p><p><br></p><p>But I think move operations are stupid, =
for the codes are very similar between different uses.<br>When I write thos=
e operations, I often make mistakes to do these things, and it's diffic=
ult to change and maintain.</p>
<p>I think this code could be replaced as</p><p>#include<cstdio><br>c=
lass f<br>{<br>=A0std::FILE *fp;<br>public:<br>=A0std::FILE* get(){return f=
p;}<br>=A0f(const char *p):fp(std::fopen(p,"w")){}<br>//copy oper=
ations deleted<br>
=A0f(const f&)=3Ddelete;<br>=A0f& operator=3D(const f&)=3Ddelet=
e;</p><p>//move operations defined<br>=A0f(f&& bmv) noexcept =3Daut=
o;<br>=A0f& operator=3D(f&&) noexcept =3Dauto;<br>=A0<br>=A0~f(=
){fclose(fp);}<br>};</p>
<p>int main()<br>{<br>=A0f a("324.txt");<br>=A0return 0;<br>}</p>=
<p><br></p><p>Of course. this replace has its conditions.<br>It needs all i=
ts members are "auto-moved".</p><p>You may say: why you think thi=
s will bring efficiency?</p>
<p>You know we will have concept. So containers could find this type is &qu=
ot;auto-moved", they can directly use memcpy,memmove to optimize it.<b=
r>And many no need operations could be optimized.</p></div></blockquote>
<div>This can be, and is, already done. The standard already has something =
like "auto-moved": is_trivially_move_constructible and is_trivial=
ly_move_assignable. However, your above type does *not* qualify, because th=
e move operation can't simply use memcpy and memmove -- they must also =
zero out the original pointer, and (for the move assignment) release the de=
stination pointer before clobbering it.</div>
<div><br></div><div>Adding the ability to detect the case where memcpy is e=
quivalent to move-construct-and-destroy-original might be interesting, but =
it's not immediately obvious to me what safety guarantees would be nece=
ssary to ensure that. (Essentially, we'd want to determine that the mov=
ed-from state is in some sense trivially-destructible.)</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><p>std::vector<f> vec=
;<br>vec.emplace_back("32.txt"):<br>When it do such things, it co=
uld directly called memcpy, and former resources could directly be destory,=
and I don't need to do the following sentenses:<br>
1.=A0 if(this!=3D&bmv)<br>2.=A0 bmv.fp=3Dnullptr;<br>3.=A0 allocator.de=
construct(*this);<br>4.=A0allocator.destory(this,1);</p><p>I just need to d=
o:<br>1.=A0 memcpy(,,);<br>2.=A0 allocator.destory(vec.data(),vec.size());<=
/p><p>This will be very very fast.</p>
</div></blockquote><div>Do you have benchmarks? Have you determined whether=
compilers will already optimize the code down to the same thing?</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex">
<div dir=3D"ltr"><p>2.<br>swap can be automatic generated too.<br></p></div=
></blockquote><div>This has been proposed here before.=A0<br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex">
<div dir=3D"ltr"><p>3.<br>+,-,*,/ ....They can all auto generated +=3D,-=3D=
,*=3D,/=3D<br>i++.<br>Those operations could make class types closer to int=
ernal types=A0</p></div></blockquote><div>This part hasn't been, but th=
e response to such proposals in the past has often been "let's get=
a reflection mechanism and implement this using that".<br>
</div><div><br></div><div>I assume you mean to implement + and ++ in terms =
of a user-provided +=3D, and so on? FWIW, that can already be done with rea=
sonably-elegant syntax via CRTP.</div></div></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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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 />
--047d7bf0d6c25084b904f0af62d3--
.
Author: Thomas Koeppe <tkoeppe@google.com>
Date: Fri, 24 Jan 2014 07:02:24 -0800 (PST)
Raw View
------=_Part_434_23549092.1390575744960
Content-Type: text/plain; charset=UTF-8
>
> You can express this much more succinctly (and correctly!) as:
>
> struct fcloser {
> void operator()(std::FILE *fp) const { if (fp) fclose(fp); };
> };
> typedef std::unique_ptr<std::FILE*, fcloser> f;
>
That's not even necessary. Since the destructor of unique_ptr is guaranteed
to do nothing if the pointer is null, you can simply say:
*std::unique_ptr<std::FILE, int(*)(std::FILE *)>
my_file(std::fopen(filename, mode), std::fclose);*
This won't surivive moving to a shared pointer, though, since the shared
pointer's destructor calls the deleter unconditionally.
(I saw an example of this once on SE/CR, here<http://codereview.stackexchange.com/questions/4679/shared-ptr-and-file-for-wrapping-cstdio-update-also-dlfcn-h>
..)
--
---
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_434_23549092.1390575744960
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div class=3D"gmail_quote"><div>You can express this much more succinct=
ly (and correctly!) as:</div><div><br></div><div>struct fcloser {</div><div=
> void operator()(std::FILE *fp) const { if (fp) fclose(fp); };</div>
<div>};</div><div>typedef std::unique_ptr<std::FILE*, fcloser> f;</di=
v></div></div></blockquote><div><br></div><div>That's not even necessary. S=
ince the destructor of unique_ptr is guaranteed to do nothing if the pointe=
r is null, you can simply say:</div><div><br></div><blockquote style=3D"mar=
gin: 0 0 0 40px; border: none; padding: 0px;"><div><b><font face=3D"courier=
new, monospace">std::unique_ptr<std::FILE, int(*)(std::FILE *)> my_f=
ile(std::fopen(filename, mode), std::fclose);</font></b></div></blockquote>=
<div><br></div><div>This won't surivive moving to a shared pointer, though,=
since the shared pointer's destructor calls the deleter unconditionally.</=
div><div><br>(I saw an example of this once on SE/CR, <a href=3D"http://cod=
ereview.stackexchange.com/questions/4679/shared-ptr-and-file-for-wrapping-c=
stdio-update-also-dlfcn-h">here</a>.)</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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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_434_23549092.1390575744960--
.
Author: euloanty@live.com
Date: Fri, 24 Jan 2014 18:22:07 -0800 (PST)
Raw View
------=_Part_1008_11787581.1390616527971
Content-Type: text/plain; charset=UTF-8
"This can be, and is, already done. The standard already has something like
"auto-moved": is_trivially_move_constructible and
is_trivially_move_assignable. However, your above type does *not* qualify,
because the move operation can't simply use memcpy and memmove -- they must
also zero out the original pointer, and (for the move assignment) release
the destination pointer before clobbering it."
I don't think "they must also zero out the original pointer".
If this type is moved by yourself, you need zero them.
But if it's in containers, you needn't zero and deconstruct.
If you write a vector-like specific-type data-structure. You won't zero
and do deconstructor.You will just do destroy. Right?
when you write
f(f&& bmv) noexcept =auto;
f& operator=(f&&) noexcept =auto;
Containers will know that your type has concept "standard-moving-operations
of types" by concept-check.
template<std::stdandard_move T>
void push_back()
{
// optimized version
}
template<typename T>
void push_back()
{
// can't be optimized version
}
Then they can directly do memcpy / memmove, for it's no wrong.
For your zero-memory is needless now. For after you zero-memory, your type
will be deconstruct. It's not truly move!!
You just move your resources to new places, and deconstructor is only need
to call once but you call more than once.
--
---
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_1008_11787581.1390616527971
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>"This can be, and is, already done. The standard alre=
ady has something like "auto-moved": is_trivially_move_<wbr>constructible a=
nd is_trivially_move_assignable. However, your above type does *not* qualif=
y, because the move operation can't simply use memcpy and memmove -- they m=
ust also zero out the original pointer, and (for the move assignment) relea=
se the destination pointer before clobbering it."</div><div><br></div><div>=
<br></div><div>I don't think "they must also zero out the original pointer"=
..</div><div>If this type is moved by yourself, you need zero them.</div><di=
v><br></div><div>But if it's in containers, you needn't zero and decon=
struct.</div><div><br></div><div>If you write a vector-like specific-type d=
ata-structure. You won't zero and do deconstructor.You will just do de=
stroy. Right?</div><div><br></div><div>when you write</div><div> f(f&a=
mp;& bmv) noexcept =3Dauto;<br> f& operator=3D(f&&) no=
except =3Dauto;</div><div><br></div><div>Containers will know that your typ=
e has concept "standard-moving-operations of types" by concept-check.</div>=
<div><br></div><div>template<std::stdandard_move T></div><div>void pu=
sh_back()</div><div>{</div><div>// optimized version</div><div>}</div><div>=
<br></div><div>template<typename T></div><div><div>void push_back()</=
div><div>{</div><div>// can't be optimized version</div><div>}</div><div><b=
r></div>Then they can directly do memcpy / memmove, for it's no wrong.=
</div><div>For your zero-memory is needless now. For after you zero-me=
mory, your type will be deconstruct. It's not truly move!!</div><div><=
div>You just move your resources to new places, and deconstructor is only n=
eed to call once but you call more than once.</div><div><br></div></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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<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_1008_11787581.1390616527971--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 25 Jan 2014 16:18:22 -0800
Raw View
On sexta-feira, 24 de janeiro de 2014 18:22:07, euloanty@live.com wrote:
> when you write
> f(f&& bmv) noexcept =auto;
> f& operator=(f&&) noexcept =auto;
>
> Containers will know that your type has concept "standard-moving-operations
> of types" by concept-check.
The problem here is that your concept of "standard moving operation" is not
what the compiler considers standard. The standard for move is to move each
item, which does not imply zeroing out the origin.
Your type requires zeroing the origin if the destructor is called on the
original location.
Alternatively, the type can be memcpy'ed if the destructor is not called on
the original location, but that's not the same as what we have right now in
moving.
--
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/.
.