Topic: C++0x (was: ANSI C++ feature to be removed...)
Author: "Mirek Fidler" <cxl@iol.cz>
Date: Thu, 17 May 2001 17:36:43 GMT Raw View
> > > Banning implicit conversions would go along way toward answering
> > > the objections I've raised to lifting the ban on binding non-const
> > > references to temporaries.
> >
> > Wel, but as far as I can undrestand standard, it is banned in
current
> > ANSI C++. (see section overloading). There is no need for further rules.
And
> > it does not anything to do with our temporaries problem...
>
> If you are referring to 13.3.3.1.4 [over.ics.ref] then your argument is
> circular. Implicit conversions are banned for non-const reference
parameters
> precisely because non-const references are not permitted to be bound to
> rvalues.
You are right.
> If binding non-const references to temporaries were allowed, but implicit
> conversions were disallowed when initializing a non-const reference, then
> the above (unsafe) code examples would continue to be illegal (as they
> should). It's not clear to me, however, whether this can be achieved
> without upsetting something else.
All I can say is that actual Visual C++ compiler handles references
exactly the way I am proposing. I allows binding temporaries, but dissalows
implicit conversions. That is why I think there is a way how to fix this
issues and not to upset anything else.
Perhaps following restating would solve the problem (it is just a try
!):
13.3.3.1.4
3
A standard conversion sequence OTHER THAN IDENTITY cannot be formed if
it requires binding
a reference to non-const to an rvalue (except when binding an implicit
object parameter; see the special rules for that case in
_over.match.funcs_).
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "C. M. Heard" <heard@vvnet.com>
Date: Wed, 16 May 2001 15:13:32 GMT Raw View
"Mirek Fidler" wrote:
> C. M. Heard <heard@vvnet.com> p e v diskusn m
> p sp vku:RrfK6.7134$Up.210324@sea-read.news.verio.net...
> > Christopher Eltschka wrote:
> > > Also allow rvalues to bind to non-const references, but disallow
> > > implicit conversions for this (so binding an int variable to a
> > > long reference fails instead of silently creating a long temporary).
> > > This would make things like swap more useful.
> >
> > Banning implicit conversions would go along way toward answering
> > the objections I've raised to lifting the ban on binding non-const
> > references to temporaries.
>
> Wel, but as far as I can undrestand standard, it is banned in current
> ANSI C++. (see section overloading). There is no need for further rules. And
> it does not anything to do with our temporaries problem...
If you are referring to 13.3.3.1.4 [over.ics.ref] then your argument is
circular. Implicit conversions are banned for non-const reference parameters
precisely because non-const references are not permitted to be bound to
rvalues.
I have assumed -- wrongly, perhaps -- that the proposals to allow non-const
references to be bound to temporaries would simply lift the restriction
in 8.5.3 [dcl.init.ref] that "the reference shall be to a non-volatile const
type" when the expression initializing the reference is neither an lvalue nor
a class type that can be converted to a reference-compatible lvalue. This
would allow any reference to be bound to a temporary which is created by an
implicit conversion. That would not be a good thing. It would make the
following code fragment legal:
class integer_object {
private:
integer_object& operator= (const integer_object&);
integer_object (const integer_object&);
integer_object (void);
int& object_data; // must be bound to an external integer
public:
int object_value () { return object_data; }
explicit integer_object (int& external_data): object_data(external_data) {}
~integer_object () {}
};
long int ldata = 0; // lifting restriction without banning implicit
// conversions when binding to references lets
integer_object iobj(ldata); // iobj.object_data bind to a temporary whose
// lifetime ends when construction is complete
int main () {
return iobj.object_value(); // resulting in undefined behaviour here
}
It would also re-open the following safety hole (adapted from a recent article
by James Kanze in clc++m):
void incr (unsigned int& i) {
++i;
}
int main () {
int i = -1; // requires a conversion to be bound to
// unsigned int&, which creates a temporary
incr(i); // increments the temporary (not i),
return i; // creating unexpected behaviour here
}
If binding non-const references to temporaries were allowed, but implicit
conversions were disallowed when initializing a non-const reference, then
the above (unsafe) code examples would continue to be illegal (as they
should). It's not clear to me, however, whether this can be achieved
without upsetting something else.
Mike
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Olaf Krzikalla <Entwicklung@reico.de>
Date: Tue, 15 May 2001 17:28:02 GMT Raw View
Hi,
glancaster wrote:
> 1. Promote swap to operator status.
>
> I want to be able to say
>
> a swap b;
>
> For any type without a using declaration or namespace qualification, whether
> it's a fundamental type, in std or in some other namespace. Moreover, unless
> a programmer writes swap for a type, the compiler should generates one.
> Ideally this would be based on memberwise swap, in a similar manner as the
> default memberwise copy for copy assignment and construction. Unfortunately
> this causes problems for many classes written with C++98, but I'm sure it
> could be added somehow.
I would go one step further and propose for fundamental types (or for
integral
types or at least for bool) an atomic swap.
Best regards
Olaf Krzikalla
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Olaf Krzikalla <Entwicklung@reico.de>
Date: Sat, 12 May 2001 15:26:36 GMT Raw View
Hi,
Christopher Eltschka wrote:
> That is, the fundamental set of operations is:
>
> move
> destroy
> copy
>
> The other operations can be defined in terms of them:
>
> assign a to b:
> copy b to tmp (may throw)
> destroy a
> move tmp to a
>
> or if copy is known not to throw
> destroy a
> copy b to a
>
> swap a and b:
> move a to tmp
> move b to a
> move tmp to b
>
> Now, create, destroy and copy are supported by C++, but move is not.
> Instead, move is emulated by copy whereever it is needed (such
> "move" copies are generally detectable by the fact that they may be
> optimized away even if this violates the as-if rule). Also, it
> causes the auto_ptr trouble (which has to support a copying
> interface, which doesn't really copy, and therefore indirectly
> causes the problems with the non-constant argument of the copy
> constructor).
> Now emulating move by copy is problematic, because it
> - doesn't allow to define classes which may be moved, bot not copied
> (auto_ptr),
> - generates unnecessary overhead in cases where move could have
> been implemented much cheaper (f.ex., a simple memberwise copy
> suffices even for pointers to dynamically assigned members,
> since the source is dead anyway, i.e. is considered to be
> destructed after the move, while normal copy has to either
> make a deep copy - with all the overhead and the risk of
> excepitons - or to use tricks like copy-on-write with reference
> counting, which have their own overhead),
> - doesn't allow to write a clean generic exception safe swap
> (move allows to, since there's no reason for it to throw)
Agreed.
> Therefore I would advocate:
>
> - Add a move to C++ (for backwards compatibility, it may default
> to copy, although defaulting to member-wise move would be more
> logical, and generally more efficient)
> - Make std::swap use this move
Maybe better we should be able to specialized std::swap (actually we
could, but IIRC it's not allowed).
> - Make return use this move
I think, the current g++ solution is much better and more consistent,
because neither a copy nor a move is necessary.
I'm not sure if there are other uses for move, but with the changes
above we could avoid such a major change like the introduction of a new
fundamental operation.
Best regards
Olaf Krzikalla
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Mirek Fidler" <cxl@iol.cz>
Date: Thu, 10 May 2001 17:28:07 GMT Raw View
C. M. Heard <heard@vvnet.com> p e v diskusn m
p sp vku:RrfK6.7134$Up.210324@sea-read.news.verio.net...
> Christopher Eltschka wrote:
> > Also allow rvalues to bind to non-const references, but disallow
> > implicit conversions for this (so binding an int variable to a
> > long reference fails instead of silently creating a long temporary).
> > This would make things like swap more useful.
>
> Banning implicit conversions would go along way toward answering
> the objections I've raised to lifting the ban on binding non-const
> references to temporaries.
Wel, but as far as I can undrestand standard, it is banned in current
ANSI C++. (see section overloading). There is no need for further rules. And
it does not anything to do with our temporaries problem...
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "C. M. Heard" <heard@vvnet.com>
Date: Wed, 9 May 2001 17:52:46 GMT Raw View
Christopher Eltschka wrote:
> Also allow rvalues to bind to non-const references, but disallow
> implicit conversions for this (so binding an int variable to a
> long reference fails instead of silently creating a long temporary).
> This would make things like swap more useful.
Banning implicit conversions would go along way toward answering
the objections I've raised to lifting the ban on binding non-const
references to temporaries.
Mike
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Mirek Fidler" <cxl@iol.cz>
Date: Mon, 7 May 2001 11:55:34 GMT Raw View
> > In fact, in real life you seldom need "deep" copies of most objects.
> > What you really need is to move them beetween scope (as in function
> returns)
> > or to another memory location (as in vector expanding).
>
> I find that for most classes I write or use, if I copy at all I usually
need
> a deep copy. But often I don't want to copy at all - I want to move or
swap.
> I'm not sure if we're agreeing here or not...
I think that it is just a terminology problem.
Try to think about
Foo::Foo(Foo& src);
as of "move" constructor rather than "copy" constructor (preserve this
term for Foo::Foo(const Foo&)) and we are standing at the same point...
> In general, I agree that simpler changes are to be preferred. However in
> this case I think the addition of these core language features would
remove
> a lot of complexity and surprising behaviour from C++ code where move
> semantics are desired, so it would be worth it.
In fact, I think that some more complex solution would be fine (I would
argue about concrete details, but can understand it as whole), but I am
afraid, that it would not pass C++ comitee process... But this minor
relaxing rules would.
> addition, the return member function will rarely be implemented as it is
> only applicable when a local object is being returned (apologies for not
> stating this in my earlier post).
But that is very important and comfortable to return local objects.
Thought not possible in STL to return containers for performance reasons, we
have STL-like library with "pick" semantics and it is always pleasure to be
able to write code like:
template<T>
Vector<int> GetSortOrder(const Vector<T>&) { ... }
What you get here is functional style of programming for containers (no
need for Huskell anymore ;-). And you get it for free.
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Dennis Yelle <dennis51@jps.net>
Date: Mon, 7 May 2001 21:50:21 GMT Raw View
Mirek Fidler wrote:
[...]
> But that is very important and comfortable to return local objects.
> Thought not possible in STL to return containers for performance reasons, we
> have STL-like library with "pick" semantics and it is always pleasure to be
> able to write code like:
>
> template<T>
> Vector<int> GetSortOrder(const Vector<T>&) { ... }
>
> What you get here is functional style of programming for containers (no
> need for Huskell anymore ;-). And you get it for free.
How about a standard way for a function to get a reference to
the place to build the return object?
I think gcc has a way to do this.
I have never used it, because it is non-standard.
Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here:
http://table.jps.net/~vert/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: Tue, 8 May 2001 23:00:46 GMT Raw View
Dennis Yelle wrote:
>
> glancaster wrote:
> [...]
> > 1. Promote swap to operator status.
> >
> > I want to be able to say
> >
> > a swap b;
> >
> > For any type without a using declaration or namespace qualification, whether
> > it's a fundamental type, in std or in some other namespace. Moreover, unless
> > a programmer writes swap for a type, the compiler should generates one.
>
> Yes!
>
> In the same way that
> operator+= is more fundamental than operator+,
I'm not sure about this one. "+" is "create a new object which is
the sum of two existing objects". "+=" is "modify this object so
it reflects the sum of itself and the other one". I don't see why
the second one should be more fundamental than the first.
In principle, the first one is a constructor (it constructs a new
object). It's just that this constructor is restricted to do it's
work by calling another "real" constructor and possibly modifying
the object afterwards, and it is also restricted in a way that it
can only be used to generate temporary objects.
I've once in this group proposed a way to remove this second
restriction for functions by allowing to use functions for
declarations, like
Foo f(int); // some function
f obj(5); // obj is a Foo created by f
With operator+, one would need to use the function notation:
operator+ sum(a, b);
This would also alow type inference for those variables
(think of
vec.begin first; // typeof(vec.begin()) first(vec.begin())
vec.end last; // typeof(vec.end()) last(vec.end())
), but IIRC nobody liked that idea (therefore this here isn't
meant as proposal, but only as illustration to my point that +=
IMHO isn't more fundamental than +).
BTW, I'm designing as very-low-priority task (and only for
personal fun) my own programming language, and one of it's
principles is that there are no special constructors, but
constructors *are* value-returning functions.
> swap is more fundamental than operator=.
I'm not sure about this one. However, one can make a point for this:
operator= means "replace the old value by a copy of the rhs".
Now "replace" means "delete the old value, and store the new
one instead".
Exception safety demands that the new copy is generated before
the old value is destroyed (unless exceptions are not possible
on copying). Therefore assignment semantics + exception safety
automatically means
a = b
should be implemented as
A(b).swap(a);
where A is the type of a (which I just assumed to be a
member function). Or if swap were an operator which may
be used on rvalues, one could also use
a swap A(b)
OTOH, swap can be seen as derived from a more fundamental
operation: move. Now I'm convinced that you can write
non-throwing move whereever you can write non-throwing swap
(you could do just a swap, followed by destruction of the
source [which now contains the value of the destination]).
A swap is then just three moves:
space_for(A) tmp;
tmp = new(&tmp) A(a, __move);
new(&a) A(b, __move);
new(&b) A(tmp, __move);
That is, the fundamental set of operations is:
move
destroy
copy
The other operations can be defined in terms of them:
assign a to b:
copy b to tmp (may throw)
destroy a
move tmp to a
or if copy is known not to throw
destroy a
copy b to a
swap a and b:
move a to tmp
move b to a
move tmp to b
Now, create, destroy and copy are supported by C++, but move is not.
Instead, move is emulated by copy whereever it is needed (such
"move" copies are generally detectable by the fact that they may be
optimized away even if this violates the as-if rule). Also, it
causes the auto_ptr trouble (which has to support a copying
interface, which doesn't really copy, and therefore indirectly
causes the problems with the non-constant argument of the copy
constructor).
Now emulating move by copy is problematic, because it
- doesn't allow to define classes which may be moved, bot not copied
(auto_ptr),
- generates unnecessary overhead in cases where move could have
been implemented much cheaper (f.ex., a simple memberwise copy
suffices even for pointers to dynamically assigned members,
since the source is dead anyway, i.e. is considered to be
destructed after the move, while normal copy has to either
make a deep copy - with all the overhead and the risk of
excepitons - or to use tricks like copy-on-write with reference
counting, which have their own overhead),
- doesn't allow to write a clean generic exception safe swap
(move allows to, since there's no reason for it to throw)
Therefore I would advocate:
- Add a move to C++ (for backwards compatibility, it may default
to copy, although defaulting to member-wise move would be more
logical, and generally more efficient)
- Make std::swap use this move
- Make return use this move
Also allow rvalues to bind to non-const references, but disallow
implicit conversions for this (so binding an int variable to a
long reference fails instead of silently creating a long temporary).
This would make things like swap more useful.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "glancaster" <glancaster@ntlworld.com>
Date: Sun, 6 May 2001 12:31:50 GMT Raw View
Mirek wrote:
> One feature, which we really hate in ANSI C++ and which could be easilly
> removed:
>
> ANSI C++ prohibits non-constant operation on temporary objects.
This is a problem with your workaround for the real problem, which is...
> That causes
> pretty much confusion in some of our library code, as we sometimes like to
> use "destroy-source-on-copy" style:
Otherwise known as "pretend-to-copy-but-actually-move" ;-)
Did you learn this from std::auto_ptr? Nasty, isn't it?
I would like the new C++ standard to allow easier implementation of classes
that have trouble supporting copy semantics, but can easily support move
and/or swap semantics e.g. std::auto_ptr template, and your Foo. Some things
that would let this happen:
(I won't go into too much detail now as we're in brainstorming mode, but if
anyone is interested enough in this to follow up, I'll gladly elaborate.)
1. Promote swap to operator status.
I want to be able to say
a swap b;
For any type without a using declaration or namespace qualification, whether
it's a fundamental type, in std or in some other namespace. Moreover, unless
a programmer writes swap for a type, the compiler should generates one.
Ideally this would be based on memberwise swap, in a similar manner as the
default memberwise copy for copy assignment and construction. Unfortunately
this causes problems for many classes written with C++98, but I'm sure it
could be added somehow.
Certain usages of the template algorithm std::swap have a number of other
problems that this would solve. Plus, no-throw swap implementations, which
would be encouraged by this change, are pretty essential for a lot of
exception-safe code.
2. A move keyword (operator?). Really a special ctor. An example:
T a(move b); // Construct a by moving b.
The purpose of which is to move the contents of b into a, leaving b in a
default state. If you don't specify move for a class, the compiler generates
it for you thus:
move(T& src) :
//... default c'tion (use ctor forwarding, if added #)
{
*this swap src;
}
# yeah, I'd like this too...
So, for move to be callable T must either implement it explicitly or have a
callable swap and default ctor.
You can also use move in the following situations:
foo(move c); // Parameter is moved from c, not copied.
d move e; // Move from e to d.
3. A special return member function.
Really a combined ctor and dtor or, if you prefer to think of it that way, a
move the destroys the src rather than just putting it into a default state.
For std::auto_ptr:
return(T& src)
{
ptr = src.ptr;
}
Avoiding the current dance with auto_ptr_ref.
A return statement that returned an object would then call the first of
these that was available:
1. return(T&).
2. move(T&) then dtor.
3. copy ctor then dtor (as is always the case now).
[snip!]
Would be very interested on others thoughts about this.
Regards
Garry Lancaster
Codemill Ltd
Visit our web site at http://www.codemill.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "glancaster" <glancaster@ntlworld.com>
Date: Sun, 6 May 2001 15:12:47 GMT Raw View
Correction: Please ignore the following line from my previous post:
d move e; // Move from e to d.
- Garry.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "news.volny.cz" <cxl@iol.cz>
Date: Sun, 6 May 2001 15:15:45 GMT Raw View
> > ANSI C++ prohibits non-constant operation on temporary objects.
>
> This is a problem with your workaround for the real problem, which is...
>
> > That causes
> > pretty much confusion in some of our library code, as we sometimes like
to
> > use "destroy-source-on-copy" style:
>
> Otherwise known as "pretend-to-copy-but-actually-move" ;-)
>
> Did you learn this from std::auto_ptr? Nasty, isn't it?
I actually used it BEFORE I first saw auto_ptr... I dont think it is
nasty.
> I would like the new C++ standard to allow easier implementation of
classes
> that have trouble supporting copy semantics, but can easily support move
> and/or swap semantics e.g. std::auto_ptr template, and your Foo. Some
things
> that would let this happen:
That is partially true, but there is much more about it...
In fact, in real life you seldom need "deep" copies of most objects.
What you really need is to move them beetween scope (as in function returns)
or to another memory location (as in vector expanding).
Consider this STL caveat:
vector< vector<T> >
While this is perfectly legal, it has pretty poor performace, as there
is need to copy all inner vectors when expanding outer vector. If vector
would follow "pretend-to-copy-but-need-just-to-move" rules, there would be
no performance problem.
Furthermore, in more complicated example
struct Foo {
int something;
vector<T> data;
....
}
vector<Foo>
is again performance problem, unless vector has our "move" constructor (we
call it "pick constructor"). But in that case, C++ automatically generates
"pick" constructor for whole Foo, using standard rules for creating copy
constructors.
> 1. Promote swap to operator status.
>
> I want to be able to say
>
> a swap b;
>
> 2. A move keyword (operator?). Really a special ctor. An example:
>
> T a(move b); // Construct a by moving b.
>
> 3. A special return member function.
>
> Really a combined ctor and dtor or, if you prefer to think of it that way,
a
> move the destroys the src rather than just putting it into a default
state.
> For std::auto_ptr:
>
> return(T& src)
> {
> ptr = src.ptr;
> }
>
This would perhaps work, but what you actually do here is ADDING THREE
new major language facilities instead of REMOVING ONE minor feature. Perhaps
there is some effect in disallowing nonconst operations on temporaries to
protect shooting in your own leg, but it is largelly outweighted by
dissadvantages. Think, when standard library itself has problems with it
(auto_ptr), there is something wrong about it... Furthermore, this little
change would not break any existing code.
And, last but not least, instead of writing one "pick" constructor, you
would need to write 3 methods.
Mirek
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 7 May 2001 01:35:15 GMT Raw View
glancaster@ntlworld.com (glancaster) wrote (abridged):
> I would like the new C++ standard to allow easier implementation of
> classes that have trouble supporting copy semantics, but can
> easily support move and/or swap semantics e.g. std::auto_ptr
> template, and your Foo.
> [...]
> Would be very interested on others thoughts about this.
See for example, Anthony Simons paper, "Borrow, copy or steal? Loans and
larceny in the orthodox canonical form", OOPSLA '98, available at:
http://www.dcs.shef.ac.uk/~ajhs/publish.html
Also try searching comp.lang.c++.moderated for the word "pilfer", or for
the title "Takeover constructors".
In my view we don't need new operators or keywords. Much can be done by
adding "pilfer" arguments to existing methods, to request the different
semantics. However, as the original poster said, it would help if we
could bind temporaries to non-const references. It would also help if we
could pass arguments to destructors. I posted a request for that in this
thread a few days ago - again, try searching here for "pilfer".
Finally, some kind of block_move function would be useful. The default
implementation would be like:
template <typename T>
void block_move( T *pSrc, T *pDest, size_t count ) {
for (size_t i = 0; i != count; ++i) {
new( pSrc+i ) T( pDest[i] );
pDest[i].T::~T()
}
}
For many types this could be specialised with memmove(). User-defined
types could use a pilfer idiom. This multi-object block_move is often the
easiest level at which to provide exception safety and efficiency gains.
Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
brangdon@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Dennis Yelle <dennis51@jps.net>
Date: Mon, 7 May 2001 05:24:20 GMT Raw View
glancaster wrote:
[...]
> 1. Promote swap to operator status.
>
> I want to be able to say
>
> a swap b;
>
> For any type without a using declaration or namespace qualification, whether
> it's a fundamental type, in std or in some other namespace. Moreover, unless
> a programmer writes swap for a type, the compiler should generates one.
Yes!
In the same way that
operator+= is more fundamental than operator+,
swap is more fundamental than operator=.
Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here:
http://table.jps.net/~vert/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "glancaster" <glancaster@ntlworld.com>
Date: Mon, 7 May 2001 10:43:19 GMT Raw View
Mirek wrote:
> > > use "destroy-source-on-copy" style:
Garry Lancaster wrote:
> > Otherwise known as "pretend-to-copy-but-actually-move" ;-)
> >
> > Did you learn this from std::auto_ptr? Nasty, isn't it?
>
Mirek wrote:
> I actually used it BEFORE I first saw auto_ptr... I dont think it is
> nasty.
Wouldn't you prefer to say what you mean rather than having your move look
like a copy? With the current language you really can't so you are forced
into using this idiom, complicated code using proxies or both. "nasty"
wasn't meant to refer to the choice you *made*, but to the lack of choice
you had.
> > I would like the new C++ standard to allow easier implementation of
> > classes
> > that have trouble supporting copy semantics, but can easily support move
> > and/or swap semantics e.g. std::auto_ptr template, and your Foo. Some
> > things
> > that would let this happen:
>
> That is partially true, but there is much more about it...
>
> In fact, in real life you seldom need "deep" copies of most objects.
> What you really need is to move them beetween scope (as in function
returns)
> or to another memory location (as in vector expanding).
I find that for most classes I write or use, if I copy at all I usually need
a deep copy. But often I don't want to copy at all - I want to move or swap.
I'm not sure if we're agreeing here or not...
> Consider this STL caveat:
>
> vector< vector<T> >
>
> While this is perfectly legal, it has pretty poor performace, as there
> is need to copy all inner vectors when expanding outer vector. If vector
> would follow "pretend-to-copy-but-need-just-to-move" rules, there would be
> no performance problem.
[snipped other example]
Many classes, including std::vector, would benefit from supporting both copy
and move semantics. As there is only one copy ctor per class they cannot
currently do both in an intuitive way. Add a move ctor to the language and
this becomes much easier.
> > 1. Promote swap to operator status.
[snipped short description of operator swap]
> This would perhaps work, but what you actually do here is ADDING THREE
> new major language facilities instead of REMOVING ONE minor feature.
In general, I agree that simpler changes are to be preferred. However in
this case I think the addition of these core language features would remove
a lot of complexity and surprising behaviour from C++ code where move
semantics are desired, so it would be worth it.
The removal of the restriction you quote is being discussed in another
sub-thread - look for C.M. Heard's posting.
[snipped comments on allowing nonconst ops on temporaries]
> And, last but not least, instead of writing one "pick" constructor,
> you would need to write 3 methods.
I'm certainly not proposing that every class must have 3 extra methods
written. They are all optional and two have compiler-generated defaults. In
addition, the return member function will rarely be implemented as it is
only applicable when a local object is being returned (apologies for not
stating this in my earlier post).
Regards
Garry Lancaster
Codemill Ltd
Visit our web site at http://www.codemill.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]