Topic: Full Forwarding


Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Fri, 16 Mar 2007 14:12:18 GMT
Raw View
Alberto Ganesh Barbati ha scritto:
>
> 12.8/5: "When certain criteria are met, an implementation is allowed to
> omit the copy construction of a class object, even if the copy
> constructor and/or destructor for the object have side effects. [...]"
>

Ops. I apologize, the correct reference is 12.8/15.

G.

---
[ 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: "jam" <farid.mehrabi@gmail.com>
Date: Fri, 16 Mar 2007 14:59:52 CST
Raw View
On Mar 16, 6:12 pm, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:
> Alberto Ganesh Barbati ha scritto:
> Ops. I apologize, the correct reference is 12.8/15.
I owe a double Oops.ITs all about a silly mistake of mine. I HAVE TO
APOLOGIZE EVERY BODY.rvo is a stsndard behavoir but I did not check it
before.really sory.

apologies
FM

---
[ 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: "jam" <farid.mehrabi@gmail.com>
Date: Wed, 14 Mar 2007 16:28:18 CST
Raw View
On Mar 12, 11:48 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
wrote:
> jam ha scritto:
>
>
>
>
>
> > As a stingy programmer  , I always expect that the compiler provides
> > maximum facilities for auto optimization .But when comes to stack
> > management I find the combination of OO and C++ really wasteful .
> > I have read some stuff  on hot(rvalue) references who can help with GP
> > a lot. They  can decrease the overhead of forwarding template
> > functions ,specifically inline ones to a great extent. But  IMHO this
> > is not enough. Consider :
> > class A func(A,A);
> > A fwd(A&& a , A&& b){
> >    //forwarding function`s  body
> >    ...
> >    return func ( a , b );//forwarding line
> > };
> > In the above context if forwarding function`s  body is a trivial one
> > we can hope that the compiler generates an inline version of  'fwd'
> > with - currently - the least possible overhead ;but if this function
> > can`t be in-lined then we have to pay the negligible expense of
> > passing to pointers(references) on stack .So far so good. BUT we have
> > forgotten the overhead  of  reconstruction of the returned object;
> > whether or not the 'fwd' is in-lined  the fact that the result of
> > 'func' is copy/move-constructed by  'fwd' does not change and if 'A'
> > is huge in size then removal of this overhead will be source of
> > investigation.
>
> If I understand it correctly, the optimization you seek is RVO
> (return-value optimization). We already have it and we don't need a
> keyword to trigger it. Of course, the compiler may or may not apply RVO
> so you don't have full control on it, but that's another issue.
>
>
>
>
>
> > investigation. Now take into account a virtual function to be
> > overridden in a subclass trying to forward arguments to base class:
> > struct mission {
> >    virtual A shoot(A,A);
> >    //the rest of struct:
> >    ...
> > };
> > Struct impossible :
> >     mission
> > {
> >    A shoot (A  a  , A b )//can`t use hot-referencing.
> >    {
> >            ...
> >            return mission :: shoot(a,b);//forward to base
> >            ...
> >    };
> > };
> > The above example  is a common programming issue specifically in
> > visual programming; parameters to subclass`s overriding function MUST
> > have the same type as those of the base class`s overridden function.
>
> That's just because the function is declared virtual, it's not
> "specific" to visual programming. The problem here is that the base
> class is ill-designed: method mission::shoot() should have been declared
> taking references (or rvalue-references, as appropriate) in the first place.
>
when you write a class you are not aware how it is going to be used so
you cant declare all your functions taking references since if you do
that then you will an unnecessary overhead per function call for every
reference parameter and the return value is still unnecessarily
constructed twice .

> > So we can not device hot(rvalue)-referencing. Therefore we pay the
> > expense of both -the stack memory usage and reconstruction time-
> > overheads for returned object and arguments of  'impossible :: shoot
> > '.I would like to propose the keyword 'forward' for such cases:
>
> > A impossible:: shoot (A  a  , A b )//can`t use hot-referencing.
> >    {
> >            ...
> >            forward mission :: shoot(a,b);//forward to base
> >            ...
> >    };
>
> > And the overhead is removed. The 'forward' keyword is supposed to
> > destroy all the local variables except the arguments and transfer the
> > control to the forwarded function through an unconditional
> > jump(branch) statement; In short words, the 'forward' keyword is to
> > jump to -rather than call- the forwarded function.The 'forward'
> > instruction always replaces a return statement.
>
> The use of the term "forward" is quite misleading in this context, IMHO.
> This definitely looks more like a tail-call to me
> (http://en.wikipedia.org/wiki/Tail_call), suggesting the (re-)use of the
> keyword "goto" rather than the introduction of a new keyword with such a
> common name that it couldn't possibly be considered for fear of breaking
> existing code.
I am not concerned with the name of the keyword .I had some other word
in mind but finally chose 'forward' .By the way  'goto' looks more
interesting.
> I don't think we actually need this kind of construct. The compiler is
> already able to perform a lot of optimizations as long as the observed
> behaviour is the correct one. Why do you presume that the compiler will
> necessarily produces significantly non-optimal code to warrant the
> introduction of a brand new syntax?

Becuase when you write the code for a constructor the compiler WILL
run it and WON`T CENSOR your code.And about optimization, although the
compiler can handle some simple cases -according to platform`s IQ of
course-,I trust my own intelligence rather than the compiler because I
DO want my code platform-indipendently optimized .

Regards,

FM


---
[ 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: jdennett@acm.org (James Dennett)
Date: Thu, 15 Mar 2007 05:04:16 GMT
Raw View
jam wrote:
> On Mar 12, 11:48 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
> wrote:

[snip]

>> I don't think we actually need this kind of construct. The compiler is
>> already able to perform a lot of optimizations as long as the observed
>> behaviour is the correct one. Why do you presume that the compiler will
>> necessarily produces significantly non-optimal code to warrant the
>> introduction of a brand new syntax?
>
> Becuase when you write the code for a constructor the compiler WILL
> run it and WON`T CENSOR your code.

It's a standard-permitted, common transformation known
as RVO (return value optimization), where copying of a
return value is elided in favor of constructing it in
the memory allocated by the caller.

It's not censorship, but the compiler does not have to
call the copy constructor in this situation (or in a
number of other situations).  If a copy *is* made, it
must be done as if the copy constructor was used, but
often no copy is required.

(On a minor note of etiquette, using all caps is commonly
called "shouting", and tends to be seen as unnecessarily
aggressive.  Using *asterisks* or _underscores_ for
emphasis is more likely to convey your emphasis well.)

-- 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                      ]





Author: "=?iso-8859-1?q?Pedro_Lamar=E3o?=" <pedro.lamarao@gmail.com>
Date: Thu, 15 Mar 2007 09:55:11 CST
Raw View
On 14 mar, 19:28, "jam" <farid.mehr...@gmail.com> wrote:

> > That's just because the function is declared virtual, it's not
> > "specific" to visual programming. The problem here is that the base
> > class is ill-designed: method mission::shoot() should have been declared
> > taking references (or rvalue-references, as appropriate) in the first place.
>
> when you write a class you are not aware how it is going to be used so
> you cant declare all your functions taking references since if you do
> that then you will an unnecessary overhead per function call for every
> reference parameter and the return value is still unnecessarily
> constructed twice .

What overhead?

The only overhead I can think of is the case where you are calling a
member function of a template class, or a template function itself,
and your arguments may be fundamental types or small POD types that
you would rather copy than bind to a reference.

If you really must live in both worlds you can solve this problem with
a little template metaprogramming.

struct is_simple_enough; // There is actually stuff like this in
libstdc++'s implementation.

enable_if<is_simple_enough, A>::type
shoot (A a1, A a2)
{
  A result;
  // whatever
  return result;
}

enable_if_not<is_simple_enough, A>::type
shoot (A& a1, A& a2)
{
  A result;
  // whatever
  return result;
}

Creating the result object in the top of the function stack makes RVO
very easy for the compiler.
You can check if RVO happens in your implementation by printing stuff
to cout from the copy constructor and calling shoot for a not-simple-
enough type.

--
 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                      ]





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Thu, 15 Mar 2007 18:45:56 GMT
Raw View
jam ha scritto:
> On Mar 12, 11:48 pm, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
>
> Becuase when you write the code for a constructor the compiler WILL
> run it and WON`T CENSOR your code.And about optimization, although the
> compiler can handle some simple cases -according to platform`s IQ of
> course-,I trust my own intelligence rather than the compiler because I
> DO want my code platform-indipendently optimized .
>

About censorship, you seem to have missed this paragraph in the C++
standard:

12.8/5: "When certain criteria are met, an implementation is allowed to
omit the copy construction of a class object, even if the copy
constructor and/or destructor for the object have side effects. [...]"

Regards,

Ganesh

---
[ 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: "jam" <farid.mehrabi@gmail.com>
Date: Sat, 10 Mar 2007 14:07:12 CST
Raw View
As a stingy programmer  , I always expect that the compiler provides
maximum facilities for auto optimization .But when comes to stack
management I find the combination of OO and C++ really wasteful .
I have read some stuff  on hot(rvalue) references who can help with GP
a lot. They  can decrease the overhead of forwarding template
functions ,specifically inline ones to a great extent. But  IMHO this
is not enough. Consider :
class A func(A,A);
A fwd(A&& a , A&& b){
 //forwarding function`s  body
 ...
 return func ( a , b );//forwarding line
};
In the above context if forwarding function`s  body is a trivial one
we can hope that the compiler generates an inline version of  'fwd'
with - currently - the least possible overhead ;but if this function
can`t be in-lined then we have to pay the negligible expense of
passing to pointers(references) on stack .So far so good. BUT we have
forgotten the overhead  of  reconstruction of the returned object;
whether or not the 'fwd' is in-lined  the fact that the result of
'func' is copy/move-constructed by  'fwd' does not change and if 'A'
is huge in size then removal of this overhead will be source of
investigation. Now take into account a virtual function to be
overridden in a subclass trying to forward arguments to base class:
struct mission {
 virtual A shoot(A,A);
 //the rest of struct:
 ...
};
Struct impossible :
  mission
{
 A shoot (A  a  , A b )//can`t use hot-referencing.
 {
  ...
  return mission :: shoot(a,b);//forward to base
  ...
 };
};
The above example  is a common programming issue specifically in
visual programming; parameters to subclass`s overriding function MUST
have the same type as those of the base class`s overridden function.
So we can not device hot(rvalue)-referencing. Therefore we pay the
expense of both -the stack memory usage and reconstruction time-
overheads for returned object and arguments of  'impossible :: shoot
'.I would like to propose the keyword 'forward' for such cases:

A impossible:: shoot (A  a  , A b )//can`t use hot-referencing.
 {
  ...
  forward mission :: shoot(a,b);//forward to base
  ...
 };

And the overhead is removed. The 'forward' keyword is supposed to
destroy all the local variables except the arguments and transfer the
control to the forwarded function through an unconditional
jump(branch) statement; In short words, the 'forward' keyword is to
jump to -rather than call- the forwarded function.The 'forward'
instruction always replaces a return statement.
The usage of this keyword can be broader than just forwarding between
functions with the same(covariant) prototypes. It can include
forwarding to partially-covariant functions:

struct B: A{
 ...
};

A func( A* ,const A& ,B);

A fwd(A a1, B* bptr, B& bref , B b ,A a2 ){
 ...
 forward func( bptr ,bref ,b);
 ...
};

In the above example 'forward' destroys 'a1' & 'a2' as well as none-
argument locales and branches to 'func'. The objects 'bptr' , 'bref'
and 'b' are untouched during forwarding.
We can also destructive forwarding for functions with similar return
types but different parameters:

A func(A,A);

A fwd(A a1,class C c1,C c2){
 ...
 forward func(forward a1,a1);//Tip:new syntax
 ...
};

In this example 'forward a1' means that 'a1' remains unchanged as the
first argument to 'func' . The second argument to 'func' is copy/move-
constructed from 'a1' and 'c1' , 'c2' and all other locale variables
are destroyed before jumping into func.
We should be cautious using 'forward' keyword when dealing with C-
style('cdecl' or 'extern "C"') functions:
1. Since these functions do not perform stack clean-up, destructive
forwarding to/from them should be banned(or treated as a normal return
instruction generating warnings).
2. Forwarding from C-style functions to other ones should be banned(or
treated as a normal return instruction generating warnings).
3. Forwarding from normal functions to C-style ones maybe done with
different semantics. The forwarded function must be called (not jumped
to) and extra stack correction must be done in the caller function
prior and after forwarding.

Exact forwarding:
When the forwarding and the forwarded function(or pointer to function)
have exactly the same prototype we can write the code in a more
compressed format:

void func(int,int);

void fwd(int a ,int b){
 ...
 forward func;//same as forward func(a,b);
 ...
};


Regards
FM

---
[ 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: pongba@gmail.com
Date: Sun, 11 Mar 2007 11:24:17 CST
Raw View
On Mar 11, 4:07 am, "jam" <farid.mehr...@gmail.com> wrote:
> As a stingy programmer  , I always expect that the compiler provides
> maximum facilities for auto optimization .But when comes to stack
> management I find the combination of OO and C++ really wasteful .
> I have read some stuff  on hot(rvalue) references who can help with GP
> a lot. They  can decrease the overhead of forwarding template
> functions ,specifically inline ones to a great extent. But  IMHO this
> is not enough. Consider :
> class A func(A,A);
> A fwd(A&& a , A&& b){
>         //forwarding function`s  body
>         ...
>         return func ( a , b );//forwarding line};
>
> In the above context if forwarding function`s  body is a trivial one
> we can hope that the compiler generates an inline version of  'fwd'
> with - currently - the least possible overhead ;but if this function
> can`t be in-lined then we have to pay the negligible expense of
> passing to pointers(references) on stack .So far so good. BUT we have
> forgotten the overhead  of  reconstruction of the returned object;
> whether or not the 'fwd' is in-lined  the fact that the result of
> 'func' is copy/move-constructed by  'fwd' does not change and if 'A'
> is huge in size then removal of this overhead will be source of
> investigation. Now take into account a virtual function to be
> overridden in a subclass trying to forward arguments to base class:
> struct mission {
>         virtual A shoot(A,A);
>         //the rest of struct:
>         ...};
>
> Struct impossible :
>          mission
> {
>         A shoot (A  a  , A b )//can`t use hot-referencing.
>         {
>                 ...
>                 return mission :: shoot(a,b);//forward to base
>                 ...
>         };};
>
> The above example  is a common programming issue specifically in
> visual programming; parameters to subclass`s overriding function MUST
> have the same type as those of the base class`s overridden function.
> So we can not device hot(rvalue)-referencing. Therefore we pay the
> expense of both -the stack memory usage and reconstruction time-
> overheads for returned object and arguments of  'impossible :: shoot
> '.I would like to propose the keyword 'forward' for such cases:
>
> A impossible:: shoot (A  a  , A b )//can`t use hot-referencing.
>         {
>                 ...
>                 forward mission :: shoot(a,b);//forward to base
>                 ...
>         };
>
> And the overhead is removed. The 'forward' keyword is supposed to
> destroy all the local variables except the arguments and transfer the
> control to the forwarded function through an unconditional
> jump(branch) statement; In short words, the 'forward' keyword is to
> jump to -rather than call- the forwarded function.

If I understood you correctly, this is NOT forwarding at all.


---
[ 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: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Mon, 12 Mar 2007 13:48:25 CST
Raw View
jam ha scritto:
> As a stingy programmer  , I always expect that the compiler provides
> maximum facilities for auto optimization .But when comes to stack
> management I find the combination of OO and C++ really wasteful .
> I have read some stuff  on hot(rvalue) references who can help with GP
> a lot. They  can decrease the overhead of forwarding template
> functions ,specifically inline ones to a great extent. But  IMHO this
> is not enough. Consider :
> class A func(A,A);
> A fwd(A&& a , A&& b){
>  //forwarding function`s  body
>  ...
>  return func ( a , b );//forwarding line
> };
> In the above context if forwarding function`s  body is a trivial one
> we can hope that the compiler generates an inline version of  'fwd'
> with - currently - the least possible overhead ;but if this function
> can`t be in-lined then we have to pay the negligible expense of
> passing to pointers(references) on stack .So far so good. BUT we have
> forgotten the overhead  of  reconstruction of the returned object;
> whether or not the 'fwd' is in-lined  the fact that the result of
> 'func' is copy/move-constructed by  'fwd' does not change and if 'A'
> is huge in size then removal of this overhead will be source of
> investigation.

If I understand it correctly, the optimization you seek is RVO
(return-value optimization). We already have it and we don't need a
keyword to trigger it. Of course, the compiler may or may not apply RVO
so you don't have full control on it, but that's another issue.

> investigation. Now take into account a virtual function to be
> overridden in a subclass trying to forward arguments to base class:
> struct mission {
>  virtual A shoot(A,A);
>  //the rest of struct:
>  ...
> };
> Struct impossible :
>   mission
> {
>  A shoot (A  a  , A b )//can`t use hot-referencing.
>  {
>   ...
>   return mission :: shoot(a,b);//forward to base
>   ...
>  };
> };
> The above example  is a common programming issue specifically in
> visual programming; parameters to subclass`s overriding function MUST
> have the same type as those of the base class`s overridden function.

That's just because the function is declared virtual, it's not
"specific" to visual programming. The problem here is that the base
class is ill-designed: method mission::shoot() should have been declared
taking references (or rvalue-references, as appropriate) in the first place.

> So we can not device hot(rvalue)-referencing. Therefore we pay the
> expense of both -the stack memory usage and reconstruction time-
> overheads for returned object and arguments of  'impossible :: shoot
> '.I would like to propose the keyword 'forward' for such cases:
>
> A impossible:: shoot (A  a  , A b )//can`t use hot-referencing.
>  {
>   ...
>   forward mission :: shoot(a,b);//forward to base
>   ...
>  };
>
> And the overhead is removed. The 'forward' keyword is supposed to
> destroy all the local variables except the arguments and transfer the
> control to the forwarded function through an unconditional
> jump(branch) statement; In short words, the 'forward' keyword is to
> jump to -rather than call- the forwarded function.The 'forward'
> instruction always replaces a return statement.

The use of the term "forward" is quite misleading in this context, IMHO.
This definitely looks more like a tail-call to me
(http://en.wikipedia.org/wiki/Tail_call), suggesting the (re-)use of the
keyword "goto" rather than the introduction of a new keyword with such a
common name that it couldn't possibly be considered for fear of breaking
existing code.

I don't think we actually need this kind of construct. The compiler is
already able to perform a lot of optimizations as long as the observed
behaviour is the correct one. Why do you presume that the compiler will
necessarily produces significantly non-optimal code to warrant the
introduction of a brand new syntax?

Regards,

Ganesh

---
[ 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                      ]