Re: Constrained Forwarding(R-Value Reference)
I am trying to resubmit the following lost article from 10 03 2007, 12:36:
Howard Hinnant wrote:
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.
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".
The if clause might have ended with:
throw_my_exception();
Sorry, i so not understand <what> have ended into "throw_my_exception()".
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.
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)".
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:{
A a1
if (foo())
{
A @a2(a1);
a1:}
without "else" it can be error: "a1:}" has been executed, there is no "a1"
variable has been declared here
// Has a1 been moved from here?
A @a3(a1); // error or not?
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.
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.
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*()".
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.
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?
..
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 ]