C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Constrained Forwarding(R-Value Reference)
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Tue Mar 13, 2007 4:55 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote



On Mar 13, 2:44 pm, grizl...@yandex.ru ("Grizlyk") wrote:
Quote:

Can you give me examples of any other possible values of the expression
"auto_ptr(unique_ptr)" in the context: "in most _very_ important cases (as
for auto_ptr(unique_ptr))". I do not insist, it is just interesting why
"guess" is required here.


I read it as pseudo-C++. I thought you were talking about some kind of
conversion between the two types.

Quote:

It is very important because we will be able to make good
reliable replacement of "garbage collector" _without_
any overhead.


I think we agree that fixing auto_ptr is an important goal of adding
move semantics to C++. Could you post a use case that unique_ptr does
not support (in your opinion)?

(Also, I should point out that unique_ptr has very little to do with
garbage collection. It is an important tool for achieving
*deterministic* destruction - almost the opposite of garbage
collection)

James



---
[ 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 ]
Back to top
Grizlyk
Guest





PostPosted: Tue Mar 13, 2007 7:44 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote



James Dennett wrote:
Quote:

Fortunatelly to us, compiler easy can do "compile time testing" in most
_very_ important cases (as for auto_ptr(unique_ptr)). It is very
important becase we will be able to make good reliable replacement
of "garbage collector" _without_ any overhead.

You've said a couple of times 'auto_ptr(unique_ptr)' is an important
case. What are you talking about?

What does "couple of times 'auto_ptr(unique_ptr)'" mean?

You wrote "auto_ptr(unique_ptr)" more than once.
Well, i have seen now, that the "couple" related to "times", not to

"auto_ptr(unique_ptr)".

Quote:
The question
is what you meant by that, and what you see the issue as being
in this case?

I'm guessing that you meant something like
"auto_ptr and/or unique_ptr"

Can you give me examples of any other possible values of the expression
"auto_ptr(unique_ptr)" in the context: "in most _very_ important cases (as
for auto_ptr(unique_ptr))". I do not insist, it is just interesting why
"guess" is required here.

Quote:
but it's not clear to me which
issue you are attempting to raise regarding those smart
pointers.


What does "which issue you are attempting to raise" mean (what "issue" means
in the context of "raise")? Maybe "raise issue of auto_ptr(unique_ptr)"
means "speaking about problems of auto_ptr(unique_ptr) implementation"?

If "yes", i have written:
Quote:
It is very important because we will be able to make good
reliable replacement of "garbage collector" _without_
any overhead.

The "It" means "to do "compile time testing" for auto_ptr(unique_ptr)
implementation" here. Maybe i should write: "_This_ is very important
because..."?

--
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 ]
Back to top
Grizlyk
Guest





PostPosted: Tue Mar 13, 2007 11:59 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote



I am trying to resubmit the following lost article from 10 03 2007, 12:36:

Howard Hinnant wrote:
Quote:

I can repeat again:

Sorry for making you repeat.

Nothing to sorry, i just have noted, that used the words twice and it is not
error from my side.


Quote:
if you will struggle with "compile time attributes", you
always will get warning about "undefined behaviour" and never will get
the
warnings in opposite case of correct design. Correct desing can be like
this:

A a1
if (foo())
{
A @a2(a1);
...
}

else
{

// Has a1 been moved from here?
A @a3(a1); // error or not?

}

Now all OK.

I'm not convinced that my original code was incorrect.

Really? Your original code is true "undefined behaviour". It is the same as
the following example:

if (condition)std::move(a1);
std::move(a1);

if "condition" is true, you will get "double move" error. So compiler can
only warn you about the possible error, compiler can not improve your
design.

The previous "double move" error is the same one as error of access to
memory that already has been destroyed by "delete":

if (condition)delete a1;
delete a1;

You must _not_ work with "delete" like in the example and must _not_ write
the same with "std::move()".

Now any could ask: we do not require any "attributes" for "delete", why we
need "attributes" for "moveable"?

Because we want to have _reliable_ "dynamic memory variable" - as well
suitable for usage as "auto memory" does (garbage collector is other way to
make _reliable_ "dynamic memory variable" but (unlike to "moveable") for the
cost of perfomance lost).

The "delete" is _low_ level feature to only mark dynamic memory free, it
does not intend to be the same as "auto memory variable". The "delete" must
be encapsulated into wrapper, and the wrapper already must be the same as
"auto variable", but it can not be done without the "attributes" due to
nature of "moveable data type".


Quote:
The if clause might have ended with:

throw_my_exception();

Sorry, i so not understand <what> have ended into "throw_my_exception()".

Quote:
I know that this function is never going to return, thus the "else"
isn't needed.

There are no standard C++ function attribute as "never return". If the
attribute is exist for your compiler, compier will not produce any warnings
here.

Quote:
But the compiler has no way to know that short of whole
program analysis (which might have to be delayed until run time if
throw_my_exception() lives in a "plug-in".

Again, it is just wrong design, you must not implicitly rely on the fact
that unknow function will never return and must not write like this:

extern char *src;
extern char *dst;
{
if(condition){ dst=0; my_funct(); }

//you think my_funct(); will never return
//so you do not place "else" here
memcpy(dst,src,100);
}

You must decide: either function will return, or will not and write
appropriate code.


Also i have said, that if you are sure, that you never will return from the
true condition branch, but simultaneously do not want to explicit write the
fact with "else", "return", "break" and so on, you can write like this:

if(condition){..}
a1:(ctor);

The "a1:(ctor);" will produce no code, it is compile time directive of
compiler that from the point "a1" will always have "ctor" attribute, in
spite of "if(condition)".


Quote:
You must take in account, that "moveable" is specific and
_limited_ data type, as "const", we can not use limited type in free
manner.
We can not write for example like this:

Hmm... so can't move from just any type?

You can move from "moveable" or "copyable", but you must do it in correct
manner. This is the same as you must not working with "copyable" out of its
scope:

{
int a;
a=0;
}
//error "a" is not exist here
a=1;

In fact, the expression "moveable type a2(a1);" is the same as "}" but only
for "a1"

a1:{
Quote:
A a1
if (foo())
{
A @a2(a1);

a1:}
Quote:
...
}


without "else" it can be error: "a1:}" has been executed, there is no "a1"
variable has been declared here

Quote:
// Has a1 been moved from here?
A @a3(a1); // error or not?


Quote:
In generic code I would like
to move things around without knowing much about the type. Maybe
something like:

template <class It> It& increment(It&);

"It&" means "reference to copyable", so you have required much from the type
"It" to be "copyable". Any "moveable" (as auto_ptr) can not be used for the
template.

Quote:
template <class It, class T
It
foo(It first, It last, const T& x)
{

"const T&" means "reference to const copyable", so you have required from
the type "T" to be "copyable". Any "moveable" (as auto_ptr) can not be used
for the template.

Quote:
It i = first;
while (increment(i) != last)
{
if (!(*i == x))
{
*first = std::move(*i);
++first;
}
}
return first;
}

At the time I write this generic code, I don't know the type of *i, but
I want the code to treat *i as an rvalue because I know that I'll never
need the value stored at *i again. But I'm not sure how the compiler
will know that.

I can not say any about "rvalue" in the example. All depends from
declarations, for example, from declaration of "It::operator*()".

Quote:
To the compiler it may look like I'm moving from the
same lvalue over and over.

It will be easy to understand, if you will place here all declarations. It
seems to me that you are detecting weak points only dute to declarations are
absent. Compiler can not compile the template at the point of declaration.
All tests for the template can be done only at the point of instantiating.

Place here any instantiateable code.

Quote:
Is my above example code:

1. A compile time error?
2. ...

The template can not be instantiating at the point of declaration. There are
no syntax errors if assuming that all undeclared names will be declared
correctly during instantiating. I (and compiler too) can no guess what do
you mean. Too many undeclared things.

Consider:

template<class T>int foo(){ return static_cast<int>(T(0)); }

Is my above example:
1. A compile time error?
2. A warning about undefined behavior?
..

Quote:
If the answer is 4 (requires "runtime") I fear that much (most?) of the
code I write will require this keyword. If I have to nearly always
write "runtime" anyway I might get lulled into believing that my
double-move compile time errors are always just noisy false positives.


1.
The "compile time attributes for moveable" is stuff intended to work cheafly
with auto_ptr-like RAII wrappers, and the "compile time attributes" can not
be appied for all possible runtime conditions.

But in spite of this limitation, "compile time attributes" can help user to
explicitly express what he want to get with the wrapper, and can help to
detect some important errors for it. The stuff is not intended to be "total
protection system", trying to detect all possible holes in your program.

If you will follow the compile time attribute abilities (instead of fight
with them or ignoring them), you will get _reliable_ code similar to this:

{
int a;
a=0;
}
//error "a" is not exist here
a=1;


Also it is important, that we can write compiler with partial support of the
attributes. Compiler for the first step can detect its syntax and silently
ignoring them, so the "integrated moveable concept" (unlike "r-value
reference") is upgradeable.

It is important that "integrated moveable concept" (unlike "r-value
reference") with its keyword "moveable" does not struggle with ordinary C++
style of type declarations and allows to user to express all possible useful
combinations of all types: "const, volatile, moveable, copyable ...".

2.
Note, in your example you are using "It" as a kind of pointer here
"*first++=". Do you want to be shure, that compiler will warn you about the
possible "double move"?

Pointers by its definition is simplest kind of "runtime template". Compiler
can not trace any compile time attributes for runtime templates _even_ for
"copyable data type". Consider:

-- cut here --

#include <stdio.h>

namespace
{
const char *p=0;

void foo()
{
char a[]="hello";
p=a;
printf("My message: %s\n",p);
}

//namespace
}

int main()
{
foo();
//error "*p is not exist here" is not detected
printf("My message: %s\n",p);
}

-- cut here --

Do you want to say, that your programs are just total array of pointers and
you always will use runtime templates? I am not sure.

--
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 ]
Back to top
Howard Hinnant
Guest





PostPosted: Wed Mar 14, 2007 4:58 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

In article <et7a0h$mp0$1 (AT) aioe (DOT) org>, "Grizlyk" <grizlyk1 (AT) yandex (DOT) ru>
wrote:

Quote:
The if clause might have ended with:

throw_my_exception();

Sorry, i so not understand <what> have ended into "throw_my_exception()".

struct A {...};
A save_state;

void throw_my_exception {throw my_exception();}

void f()
{
A a1;
// ...
if (there_is_an_error)
{
save_state = std::move(a1);
throw_my_exception();
}
// ...
A a2 = std::move(a1); // compile-time error?
// ...
}

Quote:
Do you want to say, that your programs are just total array of pointers and
you always will use runtime templates? I am not sure.

I was trying to express that the use of move semantics for the templated
functions in <algorithm> is an important application. I have gone
through the exercise of implementing <algorithm> and using move in the
appropriate places. I am unclear how your design fares for this task.
Will I need to use the "runtime" keyword to keep the compiler from
flagging an error, either at template definition or instantiation time?

The templated code I showed earlier was a subset of a slightly modified
implementation of std::remove, as coded under the current rvalue
reference proposal.

The code I showed used a helper function: increment(i) to hide the ++i
from the compiler. While this isn't how I coded std::remove, such use
is not unheard of
(http://www.boost.org/libs/iterator/doc/iterator_adaptor.html).

Actually, even without the helper increment() function, the compiler
can't really know what ++i means unless i is a scalar, or it has
immediate access to the definition of operator++() for that type (which
could be in another translation unit or dynamic library).

template <class FwdIt, class T>
FwdIt
remove(FwdIt first, FwdIt last, const T& value)
{
first = std::find(first, last, value);
if (first != last)
{
FwdIt i = first;
while (++i != last)
{
if (!(*i == value))
{
*first = std::move(*i);
++first;
}
}
}
return first;
}

And perhaps this is instantiated with:

FwdIt = std::list<std::string>::iterator
T = std::string

Is this possible with your design? What is the syntax? If it does not
require the "runtime" keyword, why not?

-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 ]
Back to top
Pedro Lamarão
Guest





PostPosted: Wed Mar 14, 2007 5:00 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

On 13 mar, 20:59, "Grizlyk" <grizl...@yandex.ru> wrote:

Quote:
template <class It> It& increment(It&);

"It&" means "reference to copyable", so you have required much from the type
"It" to be "copyable". Any "moveable" (as auto_ptr) can not be used for the
template.

lt& doesn't mean "reference to copyable", it means "reference to
lvalue".
Quote:

template <class It, class T
It
foo(It first, It last, const T& x)
{

"const T&" means "reference to const copyable", so you have required from
the type "T" to be "copyable". Any "moveable" (as auto_ptr) can not be used
for the template.

Just declaring the parameter as const T& doesn't require T to be
Copyable.

The following type:

struct resource {
resource ();
int query (int param) const; // query resource on certain param
private:
resource (resource const&);
resource& operator= (resource const&);
void* stuff;
};

is not Copyable.
Now let me fill in this foo function:

template <typename Iterator, typename T>
Iterator
foo (Iterator begin, Iterator end, T const& t) {
for (; begin != end; ++begin) {
int result = t.query(*begin);
// operate with result somehow.
}
return begin;
}

Now, observe the following:

vector<int> params;
bar b;
foo(params.begin(), params.end(), b);

b is an lvalue binding to a const referente to lvalue, and b is of
type bar, and bar is not Copyable.
That declaration does not require the type bar to be Copyable.
references to lvalues are not necessarily references to values of
Copyable types.
lvalues are lvalues, Copyable types are Copyable types.

--
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 ]
Back to top
Grizlyk
Guest





PostPosted: Wed Mar 14, 2007 5:38 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

tasjaevan (AT) gmail (DOT) com wrote:
Quote:

Can you give me examples of any other possible values of the expression
"auto_ptr(unique_ptr)" in the context: "in most _very_ important cases
(as
for auto_ptr(unique_ptr))". I do not insist, it is just interesting why
"guess" is required here.


I read it as pseudo-C++. I thought you were talking about some kind of
conversion between the two types.

As I can understand, auto_ptr with move semantics was called "unique_ptr",
but really they do the same. So do we need new name for auto_ptr? I think
no.

Quote:

It is very important because we will be able to make good
reliable replacement of "garbage collector" _without_
any overhead.


I think we agree that fixing auto_ptr is an important goal of adding
move semantics to C++. Could you post a use case that unique_ptr does
not support (in your opinion)?

Probably i do not understanf the question. Without adding move semantics
into C++, reliable auto_ptr can not be implemented, because auto_ptr is not
copyable data type. The "r-value reference" is _not_ best way to add move
semantics because ... ( i already have listed 6 points of deisagreement with
the "r-value reference" in the thread and still no one has denied my reasons
in essence and proved that i was wrong ).

Quote:

(Also, I should point out that unique_ptr has very little to do with
garbage collection. It is an important tool for achieving
*deterministic* destruction - almost the opposite of garbage
collection)

Maybe, but I am not sure, that anybody has tryed to reach "deterministic
destruction" designing "auto_ptr". As i can understand, the purpose of
"auto_ptr" is hiding explicit memory allocation, as "auto" memory do: we are
declaring auto object of auto_ptr class and its "dynamic" memory (that
auto_ptr owns) looks like "auto" memory. So auto_ptr logically do the same
as garbage collector.

Only difference here that we must explicit separate "ownership" and "POD
memory pointer", so auto_ptr can not hide details of concrete memory type
_with the help of POD pointer_, as integrated to language garbage collector
could do.

Of course, we can declare more advanced (than POD pointer) interface
("holder" or "keeper") that will be suitable for all types of C++ memory:
auto, static, dynamic, dynamic_arrays and possible other and auto_ptr will
be an implementation of the interface. So templates, working with memory via
the interface will be independent from concrete memory type.

But the interface has limitations as any interface do and algorithms (unlike
to POD pointer) must take in account the fact of existing "ownership". In
other side, we have no size overhead in comparison with auto memory:
auto_ptr can be implemented (assuming C++ will support moveable) with data
members of class including only one POD pointer ( sizeof(auto_ptr) ==
sizeof(POD pointer) ). The time of allocation/deallocation depends from
"new" and "delete" implementation. Probably we could implement fast "new"
and "delete" for some extraordinary classes and dynamic nemory under
auto_ptr control for them can be nearly as fast, as auto memory do.

--
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 ]
Back to top
Guest






PostPosted: Wed Mar 14, 2007 7:51 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

On Mar 14, 5:38 pm, "Grizlyk" <grizl...@yandex.ru> wrote:
Quote:
tasjae...@gmail.com wrote:

As I can understand, auto_ptr with move semantics was called "unique_ptr",
but really they do the same. So do we need new name for auto_ptr? I think
no.


Giving auto_ptr move semantics may break existing code.

Quote:

I think we agree that fixing auto_ptr is an important goal of adding
move semantics to C++. Could you post a use case that unique_ptr does
not support (in your opinion)?

Probably i do not understanf the question. Without adding move semantics
into C++, reliable auto_ptr can not be implemented, because auto_ptr is not
copyable data type. The "r-value reference" is _not_ best way to add move
semantics because ... ( i already have listed 6 points of deisagreement with
the "r-value reference" in the thread and still no one has denied my reasons
in essence and proved that i was wrong ).


Those points have not been answered because they were based on a mis-
understanding of how rvalue references work.

To make your point, please post what you think should be possible with
auto_ptr, but isn't possible with unique_ptr as proposed.


Quote:

(Also, I should point out that unique_ptr has very little to do with
garbage collection. It is an important tool for achieving
*deterministic* destruction - almost the opposite of garbage
collection)

Maybe, but I am not sure, that anybody has tryed to reach "deterministic
destruction" designing "auto_ptr". As i can understand, the purpose of
"auto_ptr" is hiding explicit memory allocation, as "auto" memory do: we are
declaring auto object of auto_ptr class and its "dynamic" memory (that
auto_ptr owns) looks like "auto" memory. So auto_ptr logically do the same
as garbage collector.


Garbage collection has the same effect as auto_ptr only in a specific
case:

a) the object's destructor only frees memory and
b) there is only one pointer to the object

In my experience, auto_ptr (and other smart pointers) are used to
manage ownership of non-stack objects. Nothing to do with memory
directly.

James

---
[ 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 ]
Back to top
Howard Hinnant
Guest





PostPosted: Wed Mar 14, 2007 10:49 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

In article <et8gu7$8ke$1 (AT) aioe (DOT) org>, "Grizlyk" <grizlyk1 (AT) yandex (DOT) ru>
wrote:

Quote:
As I can understand, auto_ptr with move semantics was called "unique_ptr",
but really they do the same. So do we need new name for auto_ptr? I think
no.
...
( i already have listed 6 points of deisagreement with
the "r-value reference" in the thread and still no one has denied my reasons
in essence and proved that i was wrong ).

Your first point was:

Quote:
1. No auto_ptr support.
======================
And I've reread that point several times. I'm still failing to see how

the rvalue reference package is lacking in this area.

I recently wrote to another forum what I perceive as the major problem
with our current auto_ptr and why it needs to be replaced. I am
repeating that text here to answer why I believe auto_ptr needs a new
name:

My problem with auto_ptr stems from its use as a value_type in
sequence-modifying (user-written) generic code.  The fear stems from
early implementations of std::sort, but I think the same type of problem
could occur in other sequence modifying algorithms:

template<class RandomAccessIterator, class Compare>
void
sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
   ...
   // choose a partition element with RandomAccessIterator i
// and store it in a local
   value_type median = *i;
   // Now partition sequence with respect to median
   ...
   // median never assigned back into the range.
//  Why would I? *i is still there!
}

Now when you call this with say:

std::auto_ptr<int> my_array[10];
.
std::sort(my_array, my_array+10, indirect_less<int>());

then you are likely to get a run time error (i.e. a crash).  The cause
of the problem is that when the generic code author writes:

   value_type median = *i;

he's thinking *copy*.  *i should remain unchanged in his mind.  But when
the type of *i is auto_ptr, then sort's author's assumptions are
incorrect.

So who's wrong?  The author of the generic code for believing that:

   value_type median = *i;

is a copy?  Or is the author of type who allows a mutating copy from an
lvalue wrong?

My belief is the latter.  So "fixing auto_ptr" would involve changing it
such that:

   value_type median = *i;

causes a compile time error (to prevent the run time error in the
generic code).  In non-generic code, this means that:

auto_ptr<A> p1;
auto_ptr<A> p2 = p1;  // must not compile

But I do not believe we can apply this fix to auto_ptr because of
backwards compatibility concerns.  Instead, people who are willing to
take the backwards compatibility hit will vote by changing their usage
to unique_ptr (which is essentially just an auto_ptr with the mutating
copy disabled -- from lvalues only).

So, suggestions for "fixing auto_ptr" should really be clear about
exactly what is being fixed, and what that cost is in terms of backwards
compatibility is.  Imho, no matter what we do to fix it, if it moves
from lvalues with copy syntax, then the very biggest problem with it
hasn't been fixed.  Any other problems auto_ptr may have are trivial
annoyances in comparison.

For more details on the auto_ptr/unique_ptr issues, please see:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1856.html#20.4.5
%20-%20Class%20template%20auto_ptr

-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 ]
Back to top
Grizlyk
Guest





PostPosted: Thu Mar 15, 2007 7:53 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

Howard Hinnant wrote:
Quote:

The if clause might have ended with:

throw_my_exception();

Sorry, i so not understand <what> have ended into "throw_my_exception()".

struct A {...};
A save_state;

void throw_my_exception {throw my_exception();}

void f()
{
A a1;
// ...
if (there_is_an_error)
{
save_state = std::move(a1);
throw_my_exception();
}
// ...
A a2 = std::move(a1); // compile-time error?
// ...
}

I was suspecting it. This is a case when you rely on unknown implementation
of "throw_my_exception()", that the function will never return. You probably
think compiler must take the case into account for moveable (in spite it
will not work even with copyable) and you must not explicit tell to compiler
about the fact. The accident has been considered by me:

Quote:
You must decide: either function will return, or will not and
write appropriate code.

What do you think about the consideration (skipped by you)?

Quote:
Do you want to say, that your programs are just total array of pointers
and
you always will use runtime templates? I am not sure.

I was trying to express that the use of move semantics for the templated
functions in <algorithm> is an important application.

I do not argue that "move semantics is important", but

Quote:
I have gone
through the exercise of implementing <algorithm> and using move in the
appropriate places. I am unclear how your design fares for this task.

Will I need to use the "runtime" keyword to keep the compiler from
flagging an error, either at template definition or instantiation time?


runtime templates can _not_ be controlled in compile time _even for
copyable_. I have written:

Quote:
2.
Note, in your example you are using "It" as a kind of pointer here
"*first++=". Do you want to be shure, that compiler will warn you about
the
possible "double move"?

Pointers by its definition is simplest kind of "runtime template".
Compiler
can not trace any compile time attributes for runtime templates _even_
for
"copyable data type". Consider:

What do you think about the consideration?

In other words, "moveable data type" can not make the case worse than
copyable do. The purpose of compile time attributes is not control data
hidden by pointers, but to make auto memory and dynamic memory equal.

One can see the steps of "moveable concept" appearence:

*******************************************************

1. Local holder.
================

I have some "holders" (practically using in my programs) to make correct
destruction of dynamic memory on errors or returns. Its memory must be used
only locally in the block:

extern uint field_size;
void get(char *const);
uint read(const char *const);

{
int a(1);
obj_holder<int> b(new int);
array_holder<char> c(new char[field_size]);

get(*c);
if(!*c)safe_throw<err_zptr>("no input string");

*b=read(*c);
if(!*b)break;

for(uint i=*b; i; --i)++a;
return a;
}

There is a problem here: unlike "a", i can not return address of "b" or "c"
outside of the local block. At the "}" destructors of the "holders" will
free its dynamic memory.

2. Moveable concept.
====================

To solve the last problem, we can add "ownership" term into "holder" and
define concrete "ownership transfer" behaviour.

The example of the "concrete ownership transfer behaviour" is auto_ptr
behaviour. The purpose of the auto_ptr to pass ownership to the place of
destanation in spite of auto blocks bounds.

The often application of auto_ptr's ownership transfer is one from unnamed
temporary source to named destanation variable, that is why we no need any
runtime tests to share ownership between some local blocks, because unnamed
temporary unaccessible and will be automatically deleted after transfer has
been completed.

So the kind of "pass" is "move" for auto_ptr. For auto_ptr we can not do
"copy", that is why auto_ptr is not copyable, but moveable. In order to
allow to user to express the fact of moveable data type we need "moveable"
keyword, that can be applied similarly to "const" or "volatile" keywords. We
can not use only "moveable value" or "moveable reference" instead of
ordinary moveable data type.


Of course, we can use auto_ptr with named source variable also, like this:

{
int sa(1);
auto_obj<int> sb(new int(2));
auto_array<char> sc(new char[field_size]);

{
int a(sa);
auto_obj<int> b(sb);
auto_array<char> c(sc);

get(*c);
if(!*c)safe_throw<err_zptr>("no input string");

*b=read(*c);
if(!*b)break;

for(uint i=*b; i; --i)++a;
return a;
}}

There is no problem of access of named source variable when internal block
has been executed here due to "}}" - named source variable is never used
after transfer has been completed.

But it is easy to see, that named source variable is accessible inside
internal block and between "}" in "}}". The access to named source variable
after move has been done is _always error_, never UB.

3. Compile time attributes for moveable data type.
==================================================

The cause of last error is the fact, that boundaries of blocks for "auto"
and "dynamic" memory are not coincide. Take in account, that "non-const"
applied to copyable can not help us to solve the problem, can not protect us
from access to named source variable after move has been done.

To work with "moveable" we must take in account presence of "ownership",
that does not exist for "copyable", so algorithms _can not begin to support
moveable data type_ only by adding "r-value reference" declaration -
algorithms must be _re-designed_ as they must be _re-designed_ to support
"const".

Whithout strict compiler support of detection of improper usage of moveable
data type, it will be _hard to re-design_ old existing code to support new
moveable data type, as it will be hard to re-design old existing code to
support new "const" data type if compiler will not detect "assignment to
const" error.

The purpose of "compile time attributes for moveable data type" is
attenuation boundaries of blocks for "auto" and "dynamic" memory. By nature
of dynamic memory the life-time of variables belonging to the memory is not
conjunction with ordinary blocks boundaries, controlled by compiler.

We are using the dynamic memory to make a kind of blocks for variables
across ordinary blocks boundaries, because we no need to do "copy" to pass
the variable across any ordinary block boundary, so we increase perfomans
here. But simultaneously we do not want to lose reliability and "compile
time attributes for moveable data type" makes this.

With "compile time attributes for moveable data type" the last example
logically looks like this:

{
sa:{
int sa(1);
sb:{
auto_obj<int> sb(new int(2));
sc:{
auto_array<char> sc(new char[field_size]);

{
int a(sa);
sa:}
auto_obj<int> b(sb);
sb:}
auto_array<char> c(sc);
sc:}

get(*c);
if(!*c)safe_throw<err_zptr>("no input string");

*b=read(*c);
if(!*b)break;

for(uint i=*b; i; --i)++a;
return a;
}

sc:{
auto_array<char> sc(new char[field_size]);
sc:}

}

Now we have no errors. Technically, life-time of moveable will be in
accordance with ordinary boundaries "{}", but logically moveable will be
accessible from C++ only inside its logical boundaries "variable_name:{
variable_name:}".

The sintax "variable_name:{ variable_name:}" can be suitable also, but this
can not replace compile time attibutes - declaring the logical boundaries
implicitly by class or function declaration.

outcome:

No one "r-value reference" can solve the 3 steps due to quietly ignoring
existence of the problems, "r-value reference" is too simple to help us (it
implements only small part of possible moveable data type properties, but
hard to upgrade).

*******************************************************

Quote:
The templated code I showed earlier was a subset of a slightly modified
implementation of std::remove, as coded under the current rvalue
reference proposal.

The code I showed used a helper function: increment(i) to hide the ++i
from the compiler. While this isn't how I coded std::remove, such use
is not unheard of
(http://www.boost.org/libs/iterator/doc/iterator_adaptor.html).

Actually, even without the helper increment() function, the compiler
can't really know what ++i means unless i is a scalar, or it has
immediate access to the definition of operator++() for that type (which
could be in another translation unit or dynamic library).

Again: you are mixing "moveable data type" and template instantiating. "The
compiler can't really know what ++i means" because the template can not be
instantiated at the point of declaration, but in the point of instantiating
compiler will detect all possible errors correctly.

With the help of "moveable" keyword and syntax of "attributes" you can do
all what C++ can do, there are no any limitations, just try to express what
you want, what is really stored in your mind - compiler will detects most of
your errors.

I can not guess it and probably i do not know all possible applications of
"moveable" keyword and syntax of "attributes", due to this is concept
(paradigm, idiom etc), not concrete way, similarly i do not know all
possible situations with "const" usage.

Maybe you are speaking about local attribute overriding? Do you want to
write template with concrete attribute requirements, overriding declared one
in class?

Also "attributes of moveable data type" can not make your example worse than
copyable do. The compiler can't really know what "*i++" means even for
copyable due to pointer, not due to moveable. The purpose of compile time
attributes is not control data hidden by pointers, but to make auto memory
and dynamic memory equal.

Quote:

template <class FwdIt, class T
FwdIt
remove(FwdIt first, FwdIt last, const T& value)

again: it is declaration of "copyable" data type "FwdIt" and "T". There are
no any attributes needed here.

Quote:
{
first = std::find(first, last, value);
if (first != last)
{
FwdIt i = first;
while (++i != last)
{
if (!(*i == value))
{
*first = std::move(*i);

Maybe you want to have with "std::move" local type override here: to force
copyable "*first" to use "move assignment" instead of "copy assignment"?

If "move assignment" undeclared for the concrete copyable "*first", then its
"copy assignment" will be used instead of "move assignment", no real move
will be done and no any attributes needed.

Assuming "move assignment" declared or "*first" points to true moveable data
type.

Maybe you want to protect "std::move(*i)" double move?

{
*first = std::move(*i);

//do you want error detection here?
*i;

++first;
}

again: "compile time attributes for moveable data type" can not make the
case worse than copyable do. The compiler can't really know what "*i++"
means even for copyable only due to _pointer_, not due to moveable.

You probably can to declare here "moveable_iterator" for FwdIt to make sharp
differences between copyable and moveable data types. I think we must not
declare "*first" as "copyable" if you allow "*first" to be moveable only.

The declarations can be like this:

//"base" of moveable data type
class moveable_class
{
public:
//all moveable can declare the type "internal_state"
//class internal_state;

//here "internal_state" is the same as "self class"
typedef moveable moveable_class internal_state;

// for auto_ptr-like wrapper "internal_state" is stored POD
// pointer it is unsafe if exception will occure while
// "internal_state" does not bind to wrapper
// typedef T memory* internal_state;

// "operator move" returns "moveable value"
// of "internal state" its usage is overhead
// in comparison with direct assignment
// and can be unsafe
moveable internal_state
operator< ()dtor{}

public:
moveable_class(){}

//cast from internal_state
moveable_class(const moveable internal_state&:(ctor;dtor)){}

//:(ctor;dtor) by default for "move ctor"
moveable_class(const moveable moveable_class& :(ctor;dtor)){}

//:(ctor;...) and :(ctor;dtor) by default for "move assignment"
moveable moveable_class&:(ctor;...)
operator=(const moveable moveable_class& :(ctor;dtor))ctor
{return *this;}

private:
//not copyable
moveable_class(const moveable_class&);
moveable_class& operator=(const moveable_class&);
};

//moveable_iterator
template<class T=moveable_class>
class moveable_iterator
{
moveable T auto*Sad...;...) data;

public:
//here "operator++" allow to do "<i++"
moveable moveable_iterator&:(ctor;...)
operator++ ()ctor;

moveable moveable_iterator
operator++ (const int)ctor;

//moveable reference without attributes
moveable T& operator* (){ return *data; }

//moveable reference without without explicit attributes
//by default means "the attributes can not be changed"
//moveable T&:(same;same)
//("move ctor" and "move assignment" is exception)

//operator move
moveable T::internal_state
operator< ()dtor { return <*data; }

public:
...
};

Take a look, you must not use "operator*" instead "operator<" to make move.
There are differense between "get POD pointer" and "move ownership".

Now you can be protected from double move for each step

{
*first = <i;
//error detected
*i;

++first;
//ok
*i;
}


Quote:
++first;
}
}
}
return first;
}

And perhaps this is instantiated with:

FwdIt = std::list<std::string>::iterator
T = std::string

As i know, std::list<T>::iterator and std::string have no moveable support.
There is no one declaration of moveable classes here.

Quote:

Is this possible with your design? What is the syntax?
If it does not require the "runtime" keyword, why not?

There is no one declaration of moveable classes here, only copyable, i can
not answer to the kind of question related to undeclared classes. Also
"compile time attributes for moveable data type" can not make the case worse
or better than copyable do.

--
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 ]
Back to top
Grizlyk
Guest





PostPosted: Thu Mar 15, 2007 7:58 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

Howard Hinnant wrote:
Quote:

The if clause might have ended with:

throw_my_exception();

Sorry, i so not understand <what> have ended into "throw_my_exception()".

struct A {...};
A save_state;

void throw_my_exception {throw my_exception();}

void f()
{
A a1;
// ...
if (there_is_an_error)
{
save_state = std::move(a1);
throw_my_exception();
}
// ...
A a2 = std::move(a1); // compile-time error?
// ...
}

I was suspecting it. This is a case when you rely on unknown implementation
of "throw_my_exception()", that the function will never return. You probably
think compiler must take the case into account for moveable (in spite it
will not work even with copyable) and you must not explicit tell to compiler
about the fact. The accident has been considered by me:

Quote:
You must decide: either function will return, or will not and
write appropriate code.

What do you think about the consideration (skipped by you)?

Quote:
Do you want to say, that your programs are just total array of pointers
and
you always will use runtime templates? I am not sure.

I was trying to express that the use of move semantics for the templated
functions in <algorithm> is an important application.

I do not argue that "move semantics is important", but

Quote:
I have gone
through the exercise of implementing <algorithm> and using move in the
appropriate places. I am unclear how your design fares for this task.

Will I need to use the "runtime" keyword to keep the compiler from
flagging an error, either at template definition or instantiation time?


runtime templates can _not_ be controlled in compile time _even for
copyable_. I have written:

Quote:
2.
Note, in your example you are using "It" as a kind of pointer here
"*first++=". Do you want to be shure, that compiler will warn you about
the
possible "double move"?

Pointers by its definition is simplest kind of "runtime template".
Compiler
can not trace any compile time attributes for runtime templates _even_
for
"copyable data type". Consider:

What do you think about the consideration?

In other words, "moveable data type" can not make the case worse than
copyable do. The purpose of compile time attributes is not control data
hidden by pointers, but to make auto memory and dynamic memory equal.

One can see the steps of "moveable concept" appearence:

*******************************************************

1. Local holder.
================

I have some "holders" (practically using in my programs) to make correct
destruction of dynamic memory on errors or returns. Its memory must be used
only locally in the block:

extern uint field_size;
void get(char *const);
uint read(const char *const);

{
int a(1);
obj_holder<int> b(new int);
array_holder<char> c(new char[field_size]);

get(*c);
if(!*c)safe_throw<err_zptr>("no input string");

*b=read(*c);
if(!*b)break;

for(uint i=*b; i; --i)++a;
return a;
}

There is a problem here: unlike "a", i can not return address of "b" or "c"
outside of the local block. At the "}" destructors of the "holders" will
free its dynamic memory.

2. Moveable concept.
====================

To solve the last problem, we can add "ownership" term into "holder" and
define concrete "ownership transfer" behaviour.

The example of the "concrete ownership transfer behaviour" is auto_ptr
behaviour. The purpose of the auto_ptr to pass ownership to the place of
destanation in spite of auto blocks bounds.

The often application of auto_ptr's ownership transfer is one from unnamed
temporary source to named destanation variable, that is why we no need any
runtime tests to share ownership between some local blocks, because unnamed
temporary unaccessible and will be automatically deleted after transfer has
been completed.

So the kind of "pass" is "move" for auto_ptr. For auto_ptr we can not do
"copy", that is why auto_ptr is not copyable, but moveable. In order to
allow to user to express the fact of moveable data type we need "moveable"
keyword, that can be applied similarly to "const" or "volatile" keywords. We
can not use only "moveable value" or "moveable reference" instead of
ordinary moveable data type.


Of course, we can use auto_ptr with named source variable also, like this:

{
int sa(1);
auto_obj<int> sb(new int(2));
auto_array<char> sc(new char[field_size]);

{
int a(sa);
auto_obj<int> b(sb);
auto_array<char> c(sc);

get(*c);
if(!*c)safe_throw<err_zptr>("no input string");

*b=read(*c);
if(!*b)break;

for(uint i=*b; i; --i)++a;
return a;
}}

There is no problem of access of named source variable when internal block
has been executed here due to "}}" - named source variable is never used
after transfer has been completed.

But it is easy to see, that named source variable is accessible inside
internal block and between "}" in "}}". The access to named source variable
after move has been done is _always error_, never UB.

3. Compile time attributes for moveable data type.
==================================================

The cause of last error is the fact, that boundaries of blocks for "auto"
and "dynamic" memory are not coincide. Take in account, that "non-const"
applied to copyable can not help us to solve the problem, can not protect us
from access to named source variable after move has been done.

To work with "moveable" we must take in account presence of "ownership",
that does not exist for "copyable", so algorithms _can not begin to support
moveable data type_ only by adding "r-value reference" declaration -
algorithms must be _re-designed_ as they must be _re-designed_ to support
"const".

Whithout strict compiler support of detection of improper usage of moveable
data type, it will be _hard to re-design_ old existing code to support new
moveable data type, as it will be hard to re-design old existing code to
support new "const" data type if compiler will not detect "assignment to
const" error.

The purpose of "compile time attributes for moveable data type" is
attenuation boundaries of blocks for "auto" and "dynamic" memory. By nature
of dynamic memory the life-time of variables belonging to the memory is not
conjunction with ordinary blocks boundaries, controlled by compiler.

We are using the dynamic memory to make a kind of blocks for variables
across ordinary blocks boundaries, because we no need to do "copy" to pass
the variable across any ordinary block boundary, so we increase perfomans
here. But simultaneously we do not want to lose reliability and "compile
time attributes for moveable data type" makes this.

With "compile time attributes for moveable data type" the last example
logically looks like this:

{
sa:{
int sa(1);
sb:{
auto_obj<int> sb(new int(2));
sc:{
auto_array<char> sc(new char[field_size]);

{
int a(sa);
sa:}
auto_obj<int> b(sb);
sb:}
auto_array<char> c(sc);
sc:}

get(*c);
if(!*c)safe_throw<err_zptr>("no input string");

*b=read(*c);
if(!*b)break;

for(uint i=*b; i; --i)++a;
return a;
}

sc:{
auto_array<char> sc(new char[field_size]);
sc:}

}

Now we have no errors. Technically, life-time of moveable will be in
accordance with ordinary boundaries "{}", but logically moveable will be
accessible from C++ only inside its logical boundaries "variable_name:{
variable_name:}".

The sintax "variable_name:{ variable_name:}" can be suitable also, but this
can not replace compile time attibutes - declaring the logical boundaries
implicitly by class or function declaration.

outcome:

No one "r-value reference" can solve the 3 steps due to quietly ignoring
existence of the problems, "r-value reference" is too simple to help us (it
implements only small part of possible moveable data type properties, but
hard to upgrade).

*******************************************************

Quote:
The templated code I showed earlier was a subset of a slightly modified
implementation of std::remove, as coded under the current rvalue
reference proposal.

The code I showed used a helper function: increment(i) to hide the ++i
from the compiler. While this isn't how I coded std::remove, such use
is not unheard of
(http://www.boost.org/libs/iterator/doc/iterator_adaptor.html).

Actually, even without the helper increment() function, the compiler
can't really know what ++i means unless i is a scalar, or it has
immediate access to the definition of operator++() for that type (which
could be in another translation unit or dynamic library).

Again: you are mixing "moveable data type" and template instantiating. "The
compiler can't really know what ++i means" because the template can not be
instantiated at the point of declaration, but in the point of instantiating
compiler will detect all possible errors correctly.

With the help of "moveable" keyword and syntax of "attributes" you can do
all what C++ can do, there are no any limitations, just try to express what
you want, what is really stored in your mind - compiler will detects most of
your errors.

I can not guess it and probably i do not know all possible applications of
"moveable" keyword and syntax of "attributes", due to this is concept
(paradigm, idiom etc), not concrete way, similarly i do not know all
possible situations with "const" usage.

Maybe you are speaking about local attribute overriding? Do you want to
write template with concrete attribute requirements, overriding declared one
in class?

Also "attributes of moveable data type" can not make your example worse than
copyable do. The compiler can't really know what "*i++" means even for
copyable due to pointer, not due to moveable. The purpose of compile time
attributes is not control data hidden by pointers, but to make auto memory
and dynamic memory equal.

Quote:

template <class FwdIt, class T
FwdIt
remove(FwdIt first, FwdIt last, const T& value)

again: it is declaration of "copyable" data type "FwdIt" and "T". There are
no any attributes needed here.

Quote:
{
first = std::find(first, last, value);
if (first != last)
{
FwdIt i = first;
while (++i != last)
{
if (!(*i == value))
{
*first = std::move(*i);

Maybe you want to have with "std::move" local type override here: to force
copyable "*first" to use "move assignment" instead of "copy assignment"?

If "move assignment" undeclared for the concrete copyable "*first", then its
"copy assignment" will be used instead of "move assignment", no real move
will be done and no any attributes needed.

Assuming "move assignment" declared or "*first" points to true moveable data
type.

Maybe you want to protect "std::move(*i)" double move?

{
*first = std::move(*i);

//do you want error detection here?
*i;

++first;
}

again: "compile time attributes for moveable data type" can not make the
case worse than copyable do. The compiler can't really know what "*i++"
means even for copyable only due to _pointer_, not due to moveable.

You probably can to declare here "moveable_iterator" for FwdIt to make sharp
differences between copyable and moveable data types. I think we must not
declare "*first" as "copyable" if you allow "*first" to be moveable only.

The declarations can be like this:

//"base" of moveable data type
class moveable_class
{
public:
//all moveable can declare the type "internal_state"
//class internal_state;

//here "internal_state" is the same as "self class"
typedef moveable moveable_class internal_state;

// for auto_ptr-like wrapper "internal_state" is stored POD
// pointer it is unsafe if exception will occure while
// "internal_state" does not bind to wrapper
// typedef T memory* internal_state;

// "operator move" returns "moveable value"
// of "internal state" its usage is overhead
// in comparison with direct assignment
// and can be unsafe
moveable internal_state
operator< ()dtor{}

public:
moveable_class(){}

//cast from internal_state
moveable_class(const moveable internal_state&:(ctor;dtor)){}

//:(ctor;dtor) by default for "move ctor"
moveable_class(const moveable moveable_class& :(ctor;dtor)){}

//:(ctor;...) and :(ctor;dtor) by default for "move assignment"
moveable moveable_class&:(ctor;...)
operator=(const moveable moveable_class& :(ctor;dtor))ctor
{return *this;}

private:
//not copyable
moveable_class(const moveable_class&);
moveable_class& operator=(const moveable_class&);
};

//moveable_iterator
template<class T=moveable_class>
class moveable_iterator
{
moveable T auto*Sad...;...) data;

public:
//here "operator++" allow to do "<i++"
moveable moveable_iterator&:(ctor;...)
operator++ ()ctor;

moveable moveable_iterator
operator++ (const int)ctor;

//moveable reference without attributes
moveable T& operator* (){ return *data; }

//moveable reference without without explicit attributes
//by default means "the attributes can not be changed"
//moveable T&:(same;same)
//("move ctor" and "move assignment" is exception)

//operator move
moveable T::internal_state
operator< ()dtor { return <*data; }

public:
...
};

Take a look, you must not use "operator*" instead "operator<" to make move.
There are differense between "get POD pointer" and "move ownership".

Now you can be protected from double move for each step

{
*first = <i;
//error detected
*i;

++first;
//ok
*i;
}


Quote:
++first;
}
}
}
return first;
}

And perhaps this is instantiated with:

FwdIt = std::list<std::string>::iterator
T = std::string

As i know, std::list<T>::iterator and std::string have no moveable support.
There is no one declaration of moveable classes here.

Quote:

Is this possible with your design? What is the syntax?
If it does not require the "runtime" keyword, why not?

There is no one declaration of moveable classes here, only copyable, i can
not answer to the kind of question related to undeclared classes. Also
"compile time attributes for moveable data type" can not make the case worse
or better than copyable do.

--
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 ]
Back to top
Grizlyk
Guest





PostPosted: Thu Mar 15, 2007 8:00 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

tasjaevan (AT) gmail (DOT) com wrote:
Quote:

As I can understand, auto_ptr with move semantics was called
"unique_ptr",
but really they do the same. So do we need new name for auto_ptr? I think
no.


Giving auto_ptr move semantics may break existing code.

What kind of break? The auto_ptr always was not copyable (has no copy
constructor). The little correction _must_ be done to make auto_ptr usage
less dangerous (probably some errors will be found). The correction is only
adding "moveable" to auto_ptr returned and passed by value or reference. All
existing correct moveable usage must not require any more changes. Also
people can write "using old_std::auto_ptr;" and continue to collect runtime
errors.

Quote:


I think we agree that fixing auto_ptr is an important goal of adding
move semantics to C++. Could you post a use case that unique_ptr does
not support (in your opinion)?

Probably i do not understand the question. Without adding move semantics
into C++, reliable auto_ptr can not be implemented, because auto_ptr is
not
copyable data type. The "r-value reference" is _not_ best way to add move
semantics because ... ( i already have listed 6 points of deisagreement
with
the "r-value reference" in the thread and still no one has denied my
reasons
in essence and proved that i was wrong ).


Those points have not been answered because they were based on a mis-
understanding of how rvalue references work.

So i am just fool, can not understand good thing. It is so easy, that no one
even can explain it more than "they were based on a mis-understanding"
instead answering on concrete questions in essence.

Quote:
To make your point, please post what you think should be possible with
auto_ptr, but isn't possible with unique_ptr as proposed.

I already have listed 6 points of deisagreement with the "r-value reference"
in the thread and this is exact answer on your question. If you will reply
on each of the deisagreement you will see the answer on your question.

Quote:

(Also, I should point out that unique_ptr has very little to do with
garbage collection. It is an important tool for achieving
*deterministic* destruction - almost the opposite of garbage
collection)

Maybe, but I am not sure, that anybody has tryed to reach "deterministic
destruction" designing "auto_ptr". As i can understand, the purpose of
"auto_ptr" is hiding explicit memory allocation, as "auto" memory do: we
are
declaring auto object of auto_ptr class and its "dynamic" memory (that
auto_ptr owns) looks like "auto" memory. So auto_ptr logically do the
same
as garbage collector.


Garbage collection has the same effect as auto_ptr only in a specific
case:

a) the object's destructor only frees memory and

You must not use ctor/dtor for any hidden activity instead of support of
creation of objects.

I hope, we will see in C++ different optimisation for data and code and will
see pipeline executable code with explicit "sequence points".

In the case you never will know concrete point of you non-sequence data
creation. And all required constructor must be declared, but will no
garantee that some implicit of them will not be optimized out.

Quote:
b) there is only one pointer to the object

You are confusing with POD pointer and RAII wrapper behaviours. See here:
http://www.hackcraft.net/raii . Auto_ptr is wrapper (ordinary user defined
class) and is not intended to be POD pointer.

--
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 ]
Back to top
Grizlyk
Guest





PostPosted: Thu Mar 15, 2007 10:50 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

Pedro Lamarão wrote:
Quote:

template <class It> It& increment(It&);

"It&" means "reference to copyable", so you have required much from the
type
"It" to be "copyable". Any "moveable" (as auto_ptr) can not be used for
the
template.

lt& doesn't mean "reference to copyable", it means "reference to
lvalue".

He has asked me how it can be implemented with my proposal. Try open
http://grizlyk1.narod.ru/cpp_new and find there words "lvalue". Really,
lvalue/rvalue has ablsolutely no any sense in context of data type. Lvalue
means "address can be taken" and nothing more. "Lvalue" is unrelated to
"const", "copyable" or "moveable" data type.

As i can understand, temporary can not be assigned to "non-const reference"
only due to the reference can be passed out of the temporary scope and
writing into non-existing stack of the terminated function for some people
looks like more dangerous when reading from the non-existing memory or
calling functions with random entry point, that can be done with the
temporary assigned to "const reference".

Quote:

template <class It, class T
It
foo(It first, It last, const T& x)
{

"const T&" means "reference to const copyable", so you have required from
the type "T" to be "copyable". Any "moveable" (as auto_ptr) can not be
used
for the template.

Just declaring the parameter as const T& doesn't require T to be
Copyable.

Who does argue? In order to declare moveable parameter we need write "const
moveable T&", It means "reference to const moveable". Or we need write
"moveable T&", It means "reference to moveable".

Quote:
The following type:

struct resource {
resource ();
int query (int param) const; // query resource on certain param

Are you trying to change "param"?

Quote:
private:
resource (resource const&);
resource& operator= (resource const&);
void* stuff;
};

is not Copyable.

I agree, because "copy constructor" is private.

Quote:
Now let me fill in this foo function:

template <typename Iterator, typename T
Iterator
foo (Iterator begin, Iterator end, T const& t) {

You have required "Iterator" and "T" to be copyable.

Quote:
for (; begin != end; ++begin) {
int result = t.query(*begin);
// operate with result somehow.
}
return begin;
}

But you have never used the requirement for "T" in foo<>.

Quote:

Now, observe the following:

vector<int> params;
bar b;
foo(params.begin(), params.end(), b);

b is an lvalue binding to a const referente to lvalue,

b is copyable lvalue binding to a const reference to copyable

Quote:
and b is of type bar, and bar is not Copyable.

In spite the "bar" is undeclared, i trust you.

Quote:
That declaration does not require the type bar to be Copyable.

Because you have never used the requirement to be copyable for "T" in foo<>.

Quote:
references to lvalues are not necessarily references to values of
Copyable types.

There are no reference to lavalue in the my proposals. Reference to
non-copyable (simultaneously non-moveable) can not be explicitly declared..
Do you need the declaration?

--
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 ]
Back to top
James Dennett
Guest





PostPosted: Fri Mar 16, 2007 3:09 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

Grizlyk wrote:
Quote:
Pedro Lamar�o wrote:
template <class It> It& increment(It&);
"It&" means "reference to copyable", so you have required much from the
type
"It" to be "copyable". Any "moveable" (as auto_ptr) can not be used for
the
template.
lt& doesn't mean "reference to copyable", it means "reference to
lvalue".

He has asked me how it can be implemented with my proposal. Try open
http://grizlyk1.narod.ru/cpp_new and find there words "lvalue". Really,
lvalue/rvalue has ablsolutely no any sense in context of data type. Lvalue
means "address can be taken" and nothing more. "Lvalue" is unrelated to
"const", "copyable" or "moveable" data type.

The relationship is something that exists and has been
considered in quite a lot of detail. For example, it
is usually safe to move from a temporary object (which
is of course an rvalue). There are other connections;
there are no const rvalues of builtin types, but an
lvalue of type int const is quite a reasonable thing.

There are those who attempt to apply terminology from
other areas to C++, and find that it doesn't fit well;
that's not entirely surprising. By some definitions
C++'s type system is not a "type system" -- which is
all very well, but doesn't make a piece of difference
to the fact that C++ does have a system for types, and
it is a useful one.

-- James

---
[ 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 ]
Back to top
Pedro Lamarão
Guest





PostPosted: Fri Mar 16, 2007 6:58 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

On 15 mar, 14:50, grizl...@yandex.ru ("Grizlyk") wrote:
Quote:
Pedro Lamarão wrote:

lt& doesn't mean "reference to copyable", it means "reference to
lvalue".

As i can understand, temporary can not be assigned to "non-const reference"
only due to the reference can be passed out of the temporary scope and
writing into non-existing stack of the terminated function for some people
looks like more dangerous when reading from the non-existing memory or
calling functions with random entry point, that can be done with the
temporary assigned to "const reference".

This may have been the rationale for for the current rules for
reference binding.
The rationale being accepted the rules were set.

The current working paper has new syntax for references.
References declared with this new syntax have binding new rules.
These new rules, governing this new syntax, do allow for temporaries
to be bound to references.
It has been found that these new rules satisfy the desire for
expressing Moveable.

You seem to disagree and we seem to not understand why.

Quote:
and b is of type bar, and bar is not Copyable.

In spite the "bar" is undeclared, i trust you.

My mistake, a copy and paste error.
I meant for "bar" to be "resource".

I'll try again.

You are telling me that "T const&" requires T to be Copyable.
If this is true, how can the following code be valid?

class resource {
public:
resource ();
private:
resource (resource const&);
resource& operator= (resource const&);
};

template <typename T>
void
foo (T const& t) { }

void
f () {
resource r1;
foo(r1);
}

--
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 ]
Back to top
James Dennett
Guest





PostPosted: Fri Mar 16, 2007 7:09 pm    Post subject: Re: Constrained Forwarding(R-Value Reference) Reply with quote

Grizlyk wrote:
Quote:
Howard Hinnant wrote:
The if clause might have ended with:

throw_my_exception();
Sorry, i so not understand <what> have ended into "throw_my_exception()".
struct A {...};
A save_state;

void throw_my_exception {throw my_exception();}

void f()
{
A a1;
// ...
if (there_is_an_error)
{
save_state = std::move(a1);
throw_my_exception();
}
// ...
A a2 = std::move(a1); // compile-time error?
// ...
}

I was suspecting it. This is a case when you rely on unknown implementation
of "throw_my_exception()", that the function will never return. You probably
think compiler must take the case into account for moveable (in spite it
will not work even with copyable) and you must not explicit tell to compiler
about the fact.

This is not a case of relying on an unknown implementation;
the code is very explicit, it detected an error and it
called a function to throw an exception. Clear and correct
for a human; unknowable to a compiler in general as the
implementation of throw_my_exception may not be available
to it.

As I understand the example, it was intended to be (and is,
given current proposals) correct code, given the fact that
the author knows (for example, because he wrote it) that
the function throw_my_exception really does throw. The
question is whether your proposal would allow similar code
to compile cleanly without extra overhead in the source
code or at runtime. Idioms that are robust for a human
can be opaque to a compiler; conservative rules would
have to either add runtime cost or declare the idiom shown
above to be invalid, and either would be a shame.

(Howard's put a *lot* of time into considering the rvalue
reference proposals, and my first assumption if something
looks odd when I see his rvalue reference-enabled code is
to assume that I have something to learn.)

-- James

---
[ 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 ]
Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
 


Powered by phpBB © 2001, 2006 phpBB Group