Topic: moveable data type" in comparison with "r-value reference
Author: "Sylvester Hesp" <s.hesp@oisyn.nl>
Date: Thu, 12 Apr 2007 11:55:14 CST Raw View
"Richard Smith" <richard@ex-parrot.com> wrote in message
news:gnfTh.824$NZ2.325@newsfe3-gui.ntli.net...
> Just to correct a couple of typos that crept in. (I copied an old version
> of the simple 'string' class into the post.)
>
>> string& operator=( string&& o )
>> { string(o).swap(*this); return *this; }
>
> And this needs another invocation of move:
>
> { string(std::move(o)).swap(*this); return *this; }
>
Just curious: why must a new (temporary) string be created? Wouldn't
o.swap(*this) suffice? I've read the latest proposed wording (N2118), and I
couldn't find anything about an expression like o.swap(*this) being
ill-formed as o is an r-value reference. As a matter of fact, 5/7
specifically states that, in this case (for the purpose of this function), o
is an lvalue of type string. Am I misinterpreting or missing something?
- Sylvester Hesp
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: wij@seed.net.tw
Date: Fri, 13 Apr 2007 13:05:47 CST Raw View
On 4 12 , U 12 56 , d...@boost-consulting.com (David Abrahams) wrote:
> on Wed Apr 11 2007, Richard Smith <richard-AT-ex-parrot.com> wrote:
>
> > Grizlyk wrote:
>
> >> I will try to continue to show differences between "moveable data type" and
> >> "r-value reference", in order to project, that even simplest kind of
> >> algorithms with moveable data type could not be implemented with the help of
> >> "r-value reference".
>
> > I dispute this. Let me demonstrate.
>
> > Let's invent a trivially simple algorithm that might gain from a
> > movable data type
>
> It's good of you to go to the trouble, but Howard has already
> implemented an entire standard library using rvalue references
> wherever possible, and done the timing tests to show that it produces
> dramatic improvements over the existing one when used with types that
> are move-enabled. So there's an existence proof that even nontrivial
> and complex algorithms can be implemented using rvalue references such
> that they're efficient with moveable data types.
>
> And one point you make in your post, but which I think Grizlyk keeps
> missing: using rvalue references one can write the algorithms *once*
> such that they work as efficiently as possible for both moveable and
> non-moveable data types. It isn't necessary for algorithms to
> distinguish moveable types from non-moveable data types.
>
> --
> Dave Abrahams
> Boost Consultinghttp://www.boost-consulting.com
>
> Don't Miss BoostCon 2007! ==>http://www.boostcon.com
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-...@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html ]
Sorry for the interrupt. And I don't really understand rvalue
reference.
But to my part of understanding of the move constructor
1.the moved-from source object must not be destroyed. E.g.
class A {
static int count=0;
char* _cptr;
public:
A() : _cptr(NULL) { ++count; };
~A() { --count; };
$A(A& src) : _cptr(src._cptr) {}; // $A denotes the move
constructor
}
A* buf= new 10*sizeof(A);
new(&buf[0]) A(); // A[0] contains A(), other position is
uninitialized
Then no matter how the only element (A[0]) is moved around in buf.
A::count should be 1.
2. For a non-default object becomes a default object, A destructor
call is involved in the general case. (throw might occur)
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: news@news.demon.net ("News Admin")
Date: Sun, 15 Apr 2007 15:47:47 GMT Raw View
wij@seed.net.tw wrote:
>
> Sorry for the interrupt. And I don't really understand rvalue
> reference.
> But to my part of understanding of the move constructor
> 1.the moved-from source object must not be destroyed. E.g.
>
> class A {
> static int count=0;
> char* _cptr;
> public:
> A() : _cptr(NULL) { ++count; };
> ~A() { --count; };
> $A(A& src) : _cptr(src._cptr) {}; // $A denotes the move
> constructor
> }
>
> A* buf= new 10*sizeof(A);
> new(&buf[0]) A(); // A[0] contains A(), other position is
> uninitialized
>
> Then no matter how the only element (A[0]) is moved around in buf.
> A::count should be 1.
>
> 2. For a non-default object becomes a default object, A destructor
> call is involved in the general case. (throw might occur)
But the author of the move ctor is responsible for ensuring that the
moved source object is left in a destructable state.
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: howard.hinnant@gmail.com (Howard Hinnant)
Date: Mon, 23 Apr 2007 23:03:55 GMT Raw View
In article <461e0500$0$79139$e4fe514c@news.xs4all.nl>,
"Sylvester Hesp" <s.hesp@oisyn.nl> wrote:
> "Richard Smith" <richard@ex-parrot.com> wrote in message
> news:gnfTh.824$NZ2.325@newsfe3-gui.ntli.net...
> > Just to correct a couple of typos that crept in. (I copied an old version
> > of the simple 'string' class into the post.)
> >
> >> string& operator=( string&& o )
> >> { string(o).swap(*this); return *this; }
> >
> > And this needs another invocation of move:
> >
> > { string(std::move(o)).swap(*this); return *this; }
> >
>
> Just curious: why must a new (temporary) string be created? Wouldn't
> o.swap(*this) suffice? I've read the latest proposed wording (N2118), and I
> couldn't find anything about an expression like o.swap(*this) being
> ill-formed as o is an r-value reference. As a matter of fact, 5/7
> specifically states that, in this case (for the purpose of this function), o
> is an lvalue of type string. Am I misinterpreting or missing something?
I believe you are correct Sylvester.
string& operator=( string&& o )
{ swap(o); return *this; }
should do it.
Nice example Richard, thanks.
-Howard
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: Richard Smith <richard@ex-parrot.com>
Date: Wed, 11 Apr 2007 17:39:50 CST Raw View
[Apologies if this has been sent twice]
Grizlyk wrote:
> I will try to continue to show differences between "moveable data type" and
> "r-value reference", in order to project, that even simplest kind of
> algorithms with moveable data type could not be implemented with the help of
> "r-value reference".
I dispute this. Let me demonstrate.
Let's invent a trivially simple algorithm that might gain from a movable
data type: an algorithm that removes the first n elements from a
sequence (defined by a pair of iterators in the usual way), shifts the
remaining iterators forward, and returns the new end iterator. Once the
algorithm has finished, the contents of the last n elements are in valid
but undefined state; assigning to or destroying these elements is
guaranteed to work (much like std::remove).
Here's my implementation in the current language (i.e. without rvalue
references or movable data types).
template <typename ForwardIterator, typename Size>
ForwardIterator
shift_n( ForwardIterator first, ForwardIterator last, Size n)
{
ForwardIterator dest(first);
for ( ; n && first != last; ++first, --n )
;
for ( ; first != last; ++dest, ++first )
*dest = *first;
return dest;
}
Obviously there are improvements that I would make before putting
putting this for production use -- for example, I would check that n is
positive, optimise for random access iterators (much as std::advance
does), and perhaps even consider a memmove optimisation for raw pointers
to PODs. Nevertheless it serves to illustrate the point.
And here's an example of it being used:
int main() {
int init[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> v( init, init + sizeof(init) / sizeof(*init) );
v.erase( shift_n( v.begin(), v.end(), 5 ), v.end() );
// Should print "5 6 7 8 9"
std::copy( v.begin(), v.end(),
std::ostream_iterator<int>( std::cout, " " ) );
std::cout << "\n";
}
This works fine, and in this implementation the last n elements (i.e.
the elements being erased) are untouched. However, my algorithm was
permitted to leave this elements in *any* convenient state (see
paragraph preceding the implementation), and this potentially allows me
to use a move optimisation. In the syntax of the rvalue reference
proposal, I can write this:
template <typename ForwardIterator, typename Size>
ForwardIterator
shift_n( ForwardIterator first, ForwardIterator last, Size n)
{
ForwardIterator dest(first);
for ( ; n && first != last; ++first, --n )
;
for ( ; first != last; ++dest, ++first )
*dest = std::move(*first);
return dest;
}
The only difference is that I've changed the line line *dest = *first to
use std::move. [The std::move() is a simple library helper function
defined in n1856. Compiler support beyond rvalue references is not
required to implement it.] This tells the compiler that, instead of
copying a value from *first to *dest, it should attempt to move it, and
only fall back to copying if a suitable move assignment operator doesn't
exist. This fall back behaviour is extremely important because it means
that I get the benefit of "movability" where it is supported, but
doesn't require all classes to support it.
So, for example, there is no proposal to make std::complex<> have any
"move constructors" as it wouldn't benefit from one. Basically, it's a
little struct with two POD data members -- it wouldn't be possible to
make a move constructor that was any more efficient than the (trivial)
copy constructor. So if I apply my move-enabled shift_n algorithm to a
std::vector< std::complex<double> >, it will just call the ordinary copy
assignment operator.
On the other hand, let's consider std::string. It is currently proposed
[see n1857] that this will have a move-assignment operator, as, in the
absence of copy-on-write, the copy assignment operator can be quite
expensive and a move assignment operator can do much better. Let's
imagine how the a simple string class might be written.
class string {
public:
string( char const* s = NULL )
: sz( s ? strlen(s) : 0u ), str( s ? new char[sz+1] : NULL )
{ if (s) strncpy( str, o.str, sz+1 ); }
// Copy constructor -- does dynamic allocation
string( string const& o )
: sz( o.sz ), str( new char[sz+1] )
{ strncpy( str, o.str, sz+1 ); }
// Move constructor -- does a move
string( string&& o )
: sz( o.sz ), str( o.str )
{ o.str = NULL; o.sz = 0u; }
// Swap, and copy and move assignment operators
void swap( string const& o )
{ std::swap(sz, o.sz); std::swap(str, o.str); }
string& operator=( string const& o )
{ string(o).swap(*this); return *this; }
string& operator=( string&& o )
{ string(o).swap(*this); return *this; }
// And to access the string:
char const* c_str() const { return str ? str : "\0"; }
private:
size_t sz;
char* str;
};
We can see that the move assignment operator is much more efficient than
the copy assignment operator as it doesn't need to do dynamic memory
allocation, or even any string copying. Move constructors, in general,
are supposed to leave their argument in an undefined but valid state.
In this case, it leaves the argument indistinguishable from a default
constructed string. If I apply my shift_n algorithm to a
std::vector<string>, I will get the benefit of this. (Try it! Download
ConceptGCC 4.3.0 alpha 6, which supports rvalue references, and try the
code. I've made sure that, modulo #includes, the examples are all
complete enough to compile. Put some logging in the different
constructors and try it.)
So how does this work? All of the "magic" occurs in the line
*dest = std::move(*first);
of my shift_n algorithm... so let's look at this in detail. We know
that for a (sane) mutable input iterator, operator*() will return by
non-const reference, so *first is an lvalue of type V (the value_type of
the iterator). The std::move function is a trivial little helper
declared in <utility> [see n1856], and is typically implemented as:
namespace std {
template <typename T>
typename tr1::remove_reference<T>::type&& move(T&& t) {
return t;
}
}
(Where remove_reference is the TR1 metafunction declared in <type_traits>.)
Under the modified rules of template argument decuction [14.8.2.1/3 in
the working draft, n2135], when passed an lvalue of type V (still the
value_type of the iterator), the template parameter, T, of std::move
will be deduced as V&. And under the rules for template argument
substitution [14.3.1/4], this results in the instantiation of the
specialistion:
V&& std::move<V&>( V& ) { return t; }
That is, the std::move function takes an lvalue reference argument and
changes it to an rvalue reference. No copy constructors / move
constructors are called.
The remaining thing is to find a assignment operator to accept the
result of std::move(*first). In the case of std::complex<double> (which
doesn't support move construction), we have just one assignment operator
-- the standard copy assignment operator:
complex<double>&
complex<double>::operator=( complex<double> const& );
The expression std::move(*first) is an rvalue of type
std::complex<double>. (Note it is not an expression of type
std::complex& as the type of an expression is never a reference type.)
In the rvalue reference proposal, just as in the current language,
rvalues can bind to constant references, and so this operator is called.
In this case the introduction of std::move to my shift_n algorithm has
been minimal -- no extra copies or temporaries have been made, and any
decent compiler (with inlining enabled) will totally optimise the call
to std::move away. (Try it!)
What about a class with both copy and move constructors (such as my
naive string class, above). This time, the compiler finds too overloads:
string& string::operator=( string const& o ); // copy
string& string::operator=( string&& o ); // move
Overload resolution (as modified by the rvalue reference proposal) kicks
in, and an binding an rvalue to an rvalue reference is better than
binding it to a lvalue reference [13.3.3.2/3, bullet 1, sub-bullet 4] --
and so the move constructor is chosen.
So back to your original statement:
> I will try to continue to show differences between "moveable data type" and
> "r-value reference", in order to project, that even simplest kind of
> algorithms with moveable data type could not be implemented with the help of
> "r-value reference".
I have demonstrated in considerable detail how you can use rvalue
references to implement an algorithm (my shift_n function) that will
work nicely with a movable data type (my string class). Not only that,
but my algorithm will play nicely with existing types that are "merely"
copy constructible, and it required a minimal change to the existing
code. And if I have an older algorithm than isn't move-aware (such as
my original shift_n function: the one without the std::move), it will
work just fine with classes that have dual move/copy semantics (such as
my string class).
You've raised lots of other points in your post, but let's focus on this
one point. (I'm sorry to say I don't have time to deal individually
with each point in this degree of specificity.) Do you now accept that
it is in fact possible to implement "even the simplest kind of algorithm
with movable data types [...] with the help of rvalue references"? If
not, perhaps you can find a fault in my argument?
Note -- I'm not claiming that there's anything wrong with your suggested
approach using additional compile-time attributes. I suspect that in
fact it is very similar in its power and expressiveness, though, to be
quite honest, I haven't studied it in enough detail to be sure. But the
rvalue reference proposal has detailed technical documentation, it's
included in the current working draft, it's becoming increasingly
familiar to people, and it even has an implementation (ConceptGCC).
If you think your way is better than rvalue references, you need to do
more than just demonstrate that your approach is viable, or even good --
you need to demonstrate, with specificity, what is wrong with the
current (rvalue reference) proposal. You've indicated that implementing
algorithms on movable data is one such example; I've shown this doesn't
seem to be a problem by implementing an algorithm. Now it's your turn.
Where is my argument wrong?
--
Richard Smith
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 12 Apr 2007 04:56:39 GMT Raw View
on Wed Apr 11 2007, Richard Smith <richard-AT-ex-parrot.com> wrote:
> Grizlyk wrote:
>
>> I will try to continue to show differences between "moveable data type" and
>> "r-value reference", in order to project, that even simplest kind of
>> algorithms with moveable data type could not be implemented with the help of
>> "r-value reference".
>
> I dispute this. Let me demonstrate.
>
> Let's invent a trivially simple algorithm that might gain from a
> movable data type
It's good of you to go to the trouble, but Howard has already
implemented an entire standard library using rvalue references
wherever possible, and done the timing tests to show that it produces
dramatic improvements over the existing one when used with types that
are move-enabled. So there's an existence proof that even nontrivial
and complex algorithms can be implemented using rvalue references such
that they're efficient with moveable data types.
And one point you make in your post, but which I think Grizlyk keeps
missing: using rvalue references one can write the algorithms *once*
such that they work as efficiently as possible for both moveable and
non-moveable data types. It isn't necessary for algorithms to
distinguish moveable types from non-moveable data types.
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
Don't Miss BoostCon 2007! ==> http://www.boostcon.com
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: richard@ex-parrot.com (Richard Smith)
Date: Thu, 12 Apr 2007 04:57:54 GMT Raw View
Just to correct a couple of typos that crept in. (I copied an old
version of the simple 'string' class into the post.)
Richard Smith wrote:
> class string {
> public:
> string( char const* s = NULL )
> : sz( s ? strlen(s) : 0u ), str( s ? new char[sz+1] : NULL )
> { if (s) strncpy( str, o.str, sz+1 ); }
^^^^^
"o.str" should read "s"
> void swap( string const& o )
And this should take a non-const string:
void swap( string& o );
> string& operator=( string&& o )
> { string(o).swap(*this); return *this; }
And this needs another invocation of move:
{ string(std::move(o)).swap(*this); return *this; }
> namespace std {
> template <typename T>
> typename tr1::remove_reference<T>::type&& move(T&& t) {
> return t;
> }
> }
>
> (Where remove_reference is the TR1 metafunction declared in <type_traits>.)
If you try using ConceptGCC alpha 6, you'll find it doesn't yet have
std::move in <utility>, but the above implementation will work just fine.
--
Richard Smith
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "Grizlyk" <grizlyk1@yandex.ru>
Date: Sat, 7 Apr 2007 09:19:05 CST Raw View
Pedro Lamar owrote:
>
> > > The state of the source may be unchanged, or it may be radically
> > > different. The only requirement is that the object remain in a self
> > > consistent state (all internal invariants are still intact).
>
> > The requirement is theoretically correct, but practically useless one,
> > because even auto_ptr wrapper has other behaviour.
>
> > Note, it is very important for auto_ptr that its state after "move" became
> > incorrect and user must not have access to auto_ptr during incorrect state,
> > because else we can not implement desired behaviour of auto memory
> > substitution.
>
> Observe the implementation of the "pseudo-move constructor" for
> auto_ptr in current libstdc++ main line:
>
> auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
>
> element_type*
> release() throw()
> {
> element_type* __tmp = _M_ptr;
> _M_ptr = 0;
> return __tmp;
> }
>
> After we move from __a it becomes just as if default constructed.
> So it is not true that move semantics require the moved-from object to
> have incorrect internal state.
You probably think, that NULL pointer is correct state? Maybe because
NULL pointer assigned to _M_ptr by default constructor?
It is evidently, we are speaking about useful value of _M_ptr, that
will be used in program as _correct_ address. If address of _M_ptr is
incorrect, then auto_ptr state is incorrect also.
You are trying to give control under state of auto_ptr to user just
becasue "rvalue reference" (even in theory) can not control the state
itself. It is only reason, because i do not beleive, that you will
refuse from the control, if "rvalue reference" could do this.
But "rvalue reference" can not, so you are find a reason for the
"behaviour" - we no need this, we are happy without the control.
Being "refinenment of copyable", "rvalue reference" just must not
claim to be representation of moveable, then we will have no any
problems.
> > > From a client code point of view, choosing move instead of copy means
> > > that you don't care what happens to the state of the source.
>
> > Here "copying from non-const source" and "move" are mixed. There are
> > differences beetwen them. For "move" source state _never_ will be correct or
> > UB, _always_ will be incorrect.
>
> This _never_ is artificial.
> There is no practical requirement for it.
Here http://grizlyk1.narod.ru/cpp_new you can find examples of the
practical requirements.
> This _never_ implies the above implementation of auto_ptr is wrong.
Any implementation of auto_ptr without compile time attributes is just
a point of run-time errors.
> It is not.
It is.
--
Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: grizlyk1@yandex.ru ("Grizlyk")
Date: Wed, 21 Mar 2007 23:33:18 GMT Raw View
Hello.
I will try to continue to show differences between "moveable data type" and
"r-value reference", in order to project, that even simplest kind of
algorithms with moveable data type could not be implemented with the help of
"r-value reference".
So being refinement of copyable data type, "r-value reference" can not claim
to be representation of "moveable data type" as ordinary type in C++.
>"r-value reference"
Page of "r-value reference" is
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm
Page of "moveable concept" is http://grizlyk1.narod.ru/cpp_new articles
#11-#15
Copy vs Move
============
> The state of the source may be unchanged, or it may be radically
> different. The only requirement is that the object remain in a self
> consistent state (all internal invariants are still intact).
The requirement is theoretically correct, but practically useless one,
because even auto_ptr wrapper has other behaviour.
Note, it is very important for auto_ptr that its state after "move" became
incorrect and user must not have access to auto_ptr during incorrect state,
because else we can not implement desired behaviour of auto memory
substitution.
Article "apperance of moveable concept" on my page
http://grizlyk1.narod.ru/cpp_new#14_1 coming soon.
> From a client code point of view, choosing move instead of copy means
> that you don't care what happens to the state of the source.
Here "copying from non-const source" and "move" are mixed. There are
differences beetwen them. For "move" source state _never_ will be correct or
UB, _always_ will be incorrect.
It is situation that as if we can imagine "moveable" data type sharp divided
into internal and external state, and "move" change placement of internal
state. Source object without internal state can not exist, and we may not
assign to source internal state any random value, in order to make the state
"as if correct or consistent".
Of course, we can imagine a kind of data type for which after "move" any
other (but correct) value exist for source, but we can not demand the
specific behaviour from all moveable data, originally moveable data type
must has ability to turn source after "move" into incorrect state.
> For PODs, move and copy are identical operations
> (right down to the machine instruction level).
The cause of the POD behaviour is just the fact, that POD data is copyable
data type without specific implementation of "move" and instead of "move"
using "copy".
In comparison with moveable data type, source external state of copyable
data type after "copy" _always_ remains unchanged, _never_ source state
after "copy" can be changed, because we can not get two equal copies, if
source will be changed after copy.
Binding temporaries to references
=================================
> The new reference type introduces syntax for allowing that
> functionality without changing the meaning of any existing code.
Yes, it is "without changing existing code" that r-value reference is trying
to do, instead of introducing "moveable data type" as itself.
The heroic attempt to make moveable from unchanged old code, working only
with copyable, can be ironically compared with apearence of "implicit const
reference T&&&"
template<class T>
void foo(T&&& t);
here "t" is implicitly "const", because in the case
foo<int>( int(3) );
compiler can elide copy ctor to create "t" and makes perfectly forwarding.
Note, introducing moveable data type will not require any changes to code
working with copyable and does not change execution of the code.
More on A&&
===========
> The rvalue reference is a new type, distinct from the current
> (lvalue) reference.
I think, we must note, that difference can be only behaviour. Because
semantics of term "reference" means "address", in comparison with semantics
of term "value". The difference is size of memory allocated for parameter,
passed to function:
( sizeof(parameter passed by any reference)
== sizeof(parameter passed by pointer ) )
!= sizeof(parameter passed by value )
> The most common overload set anticipated is:
>
> void foo(const A& t); // #1
> void foo(A&& t); // #2
>
> A source();
> const A const_source();
> foo(source()); // binds to #2
> foo(const_source()); // binds to #1
This is suspicional idea to make overloading by const/non-const parameter,
it can be place of vague casts and human errors.
The function
const A const_source();
is logical nonsence, because function must not limit returned _value_ of A
for other context as "const". The construction can be allowed, but can not
change "constness".
Moving from local values
========================
For "moveable data type", behaviour of objects defined only by class
_declaration_ and variable _declaration_ (as any ordinary C++ type _must_
do), "moveable data type" looks like "volatile data type" or "const data
type".
For "r-value reference", behaviour of objects defined only by concrete
_place_ of usage of variable of undefined type, _never_ by declarations (as
any ordinary C++ type _never_ must do). The "(r-value reference)" proposal
makes type of variable is secondary, but place of code is primary condition
of behaviour of variable.
Article 'differences between "rvalues", "movability" and "moveable data
type"' on my page http://grizlyk1.narod.ru/cpp_new#14_2 coming soon.
--
Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 22 Mar 2007 15:12:40 GMT Raw View
on Wed Mar 21 2007, grizlyk1-AT-yandex.ru ("Grizlyk") wrote:
> So being refinement of copyable data type, "r-value reference" can not claim
> to be representation of "moveable data type" as ordinary type in C++.
Your premise is incorrect. rvalue reference is not a refinement of
copyable data type.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ 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.comeaucomputing.com/csc/faq.html ]
Author: "=?iso-8859-1?q?Pedro_Lamar=E3o?=" <pedro.lamarao@gmail.com>
Date: Thu, 22 Mar 2007 17:34:27 CST Raw View
On 21 mar, 20:33, grizl...@yandex.ru ("Grizlyk") wrote:
> > The state of the source may be unchanged, or it may be radically
> > different. The only requirement is that the object remain in a self
> > consistent state (all internal invariants are still intact).
>
> The requirement is theoretically correct, but practically useless one,
> because even auto_ptr wrapper has other behaviour.
>
> Note, it is very important for auto_ptr that its state after "move" became
> incorrect and user must not have access to auto_ptr during incorrect state,
> because else we can not implement desired behaviour of auto memory
> substitution.
Observe the implementation of the "pseudo-move constructor" for
auto_ptr in current libstdc++ main line:
auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
element_type*
release() throw()
{
element_type* __tmp = _M_ptr;
_M_ptr = 0;
return __tmp;
}
After we move from __a it becomes just as if default constructed.
So it is not true that move semantics require the moved-from object to
have incorrect internal state.
> Article "apperance of moveable concept" on my pagehttp://grizlyk1.narod.ru/cpp_new#14_1coming soon.
>
> > From a client code point of view, choosing move instead of copy means
> > that you don't care what happens to the state of the source.
>
> Here "copying from non-const source" and "move" are mixed. There are
> differences beetwen them. For "move" source state _never_ will be correct or
> UB, _always_ will be incorrect.
This _never_ is artificial.
There is no practical requirement for it.
This _never_ implies the above implementation of auto_ptr is wrong.
It is not.
--
Pedro Lamar o
---
[ 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.comeaucomputing.com/csc/faq.html ]