Topic: anystate' qualifier


Author: "Mathias Gaunard" <loufoque@gmail.com>
Date: Thu, 12 Apr 2007 19:21:47 CST
Raw View
Here is a crazy idea that I just came up with.

I was thinking of the issue caused by the unneeded temporaries that
happened when returning std::string by value.

std::string foo()
{
    std::string s;
    /* some work on s */
    return s;
}

std::string s = foo(); // with a smart compiler doing NRVO, no
unneeded copy, construction or destruction
s = foo(); // constructs a tempory, calls s.operator=, then destructs
the temporary

A possible solution would simply to write the function that way so
that another string could be reused:

void foo(std::string& s)
{
   s = ""; // to make it empty and forget about the old contents
   /* some work on s */
}

My crazy idea was to simply allow code with the first signature to do
similar thing as the second one.

std::string foo()
{
   anystate std::string s;
   s = ""; // to make it empty and forget about the old contents
   /* some work on s */

   return s;
}

Basically, 'anystate' means that the object can be in any valid state
(after a construction and before a destruction).
With that indication, the compiler would be able to reuse the return
value in the function.

---
[ 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: nevin@eviloverlord.com ("Nevin :-] Liber")
Date: Fri, 13 Apr 2007 03:55:19 GMT
Raw View
In article <1176422460.558589.322120@y80g2000hsf.googlegroups.com>,
 "Mathias Gaunard" <loufoque@gmail.com> wrote:

> void foo(std::string& s)
> {
>    s = ""; // to make it empty and forget about the old contents
>    /* some work on s */
> }
>
> My crazy idea was to simply allow code with the first signature to do
> similar thing as the second one.
>
> std::string foo()
> {
>    anystate std::string s;
>    s = ""; // to make it empty and forget about the old contents
>    /* some work on s */
>
>    return s;
> }

They are not semantically equivalent.  Take the case where something
inside of foo throws.

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

---
[ 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: Fri, 13 Apr 2007 13:05:40 CST
Raw View
Mathias Gaunard ha scritto:
>
> void foo(std::string& s)
> {
>    s = ""; // to make it empty and forget about the old contents

It's much better to use s.clear() for that.

>    /* some work on s */
> }
>
> My crazy idea was to simply allow code with the first signature to do
> similar thing as the second one.
>
> std::string foo()
> {
>    anystate std::string s;
>    s = ""; // to make it empty and forget about the old contents
>    /* some work on s */
>
>    return s;
> }
>
> Basically, 'anystate' means that the object can be in any valid state
> (after a construction and before a destruction).

I don't get it. Of course any object can be in "any valid state". How
can it be otherwise? Why should I tell the compiler about it?

> With that indication, the compiler would be able to reuse the return
> value in the function.

It not clear to me what you mean. Anyway, a quite good optimization of
this specific scenario can be achieved with rvalue references and move
semantic. When we will have them (and we definitely will) would your
idea still be useful?

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: Greg Herlihy <greghe@pacbell.net>
Date: Mon, 16 Apr 2007 02:07:24 CST
Raw View


On 4/12/07 6:21 PM, in article
1176422460.558589.322120@y80g2000hsf.googlegroups.com, "Mathias Gaunard"
<loufoque@gmail.com> wrote:

> Here is a crazy idea that I just came up with.
>
> I was thinking of the issue caused by the unneeded temporaries that
> happened when returning std::string by value.
>
> std::string foo()
> {
>     std::string s;
>     /* some work on s */
>     return s;
> }
>
> std::string s = foo(); // with a smart compiler doing NRVO, no
> unneeded copy, construction or destruction
> s = foo(); // constructs a tempory, calls s.operator=, then destructs
> the temporary

The "named return value optimization" (NRVO) can eliminate the temporary in
the second example as well. Specifically, the NRVO optimization eliminates
the need for a temporary by extending the lifetime of the local variable
that foo() returns to be just as long as the lifetime of the temporary that
foo() would have ordinarily returned. In other words, the local variable
that foo() returns - and the temporary that holds foo()'s result (and whose
contents are copied into "s") - are one and the same.

> A possible solution would simply to write the function that way so
> that another string could be reused:
>
> void foo(std::string& s)
> {
>    s = ""; // to make it empty and forget about the old contents
>    /* some work on s */
> }

This interface for foo() is inconvenient (and inefficient) whenever the
value to be transformed is either const or otherwise needs to be preserved.
A more convenient interface for foo() would separate input from output - and
would accept input by const reference as produce output by return value. And
thanks to the NRVO, the more convenient interface could well be the more
efficient interface as well.

Greg

---
[ 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: "Mathias Gaunard" <loufoque@gmail.com>
Date: Mon, 16 Apr 2007 11:42:04 CST
Raw View
On 16 avr, 17:07, Greg Herlihy <gre...@pacbell.net> wrote:

> The "named return value optimization" (NRVO) can eliminate the temporary in
> the second example as well.

That was an example.
In a real case, the string is not simply default-constructed before,
it has any content. It can be in any state.


> This interface for foo() is inconvenient (and inefficient) whenever the
> value to be transformed is either const or otherwise needs to be preserved

> A more convenient interface for foo() would separate input from output - and
> would accept input by const reference as produce output by return value.

The whole point of the idea is to reuse a variable for the output
rather than constructing a new one.

> And
> thanks to the NRVO, the more convenient interface could well be the more
> efficient interface as well.

It is not.
I will try to explain again, since you guys don't seem to get it.

std::string s = "bar";
s = foo();

Even if NRVO is applied, a new string will be default constructed in
foo(), then operator=() will be called to transfer its contents to s,
and finally that thing will be destructed.
There are obviously useless constructions/operator=/destructions here,
since we could simply reuse s.

It has been stated that with rvalue references, those operations will
become free. That is false, they will only become cheaper.
Rvalue-references only increase performance when free storage is used,
because you just need to swap pointers. But if automatic storage is
used instead (as it is with the famous small string optimization) then
the whole content would have to be copied anyway.

If we consider that the implementation use the small string
optimization, provide rvalue references and nrvo, then the data *will*
be copied in the previous example.
If the return value can be reused, however, there is no other copy
than the ones induced by initialization from string literals.

---
[ 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: "Mathias Gaunard" <loufoque@gmail.com>
Date: Mon, 16 Apr 2007 12:47:57 CST
Raw View
On 14 avr, 04:05, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
wrote:

> I don't get it. Of course any object can be in "any valid state". How
> can it be otherwise? Why should I tell the compiler about it?

Usually, when returning a default-constructible object, you construct
it, make your modifications, then return it.
With the anystate qualifier, you tell the compiler that there is no
need to have an object in the state "just default-constructed", it
could have been initialized a while before and have various operations
done on it. Of course, if no such object is available, the default-
constructor is used.

That simply allows the compiler to reuse the return value which
becomes your local variable, and if it's not possible it does create a
new one.


---
[ 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: Tue, 17 Apr 2007 13:43:27 GMT
Raw View
Mathias Gaunard ha scritto:
> On 14 avr, 04:05, Alberto Ganesh Barbati <AlbertoBarb...@libero.it>
> wrote:
>
>> I don't get it. Of course any object can be in "any valid state". How
>> can it be otherwise? Why should I tell the compiler about it?
>
> Usually, when returning a default-constructible object, you construct
> it, make your modifications, then return it.
> With the anystate qualifier, you tell the compiler that there is no
> need to have an object in the state "just default-constructed", it
> could have been initialized a while before and have various operations
> done on it. Of course, if no such object is available, the default-
> constructor is used.
>
> That simply allows the compiler to reuse the return value which
> becomes your local variable, and if it's not possible it does create a
> new one.
>

While I understand your concern, your syntax of your proposal is
inacceptable, in my opinion. Consider your example:

  std::string s = "bar";
  s = foo();

which, according to your original post, should be addressed with:

  std::string foo()
  {
     anystate std::string s;
     s = ""; // to make it empty and forget about the old contents
     /* some work on s */
     return s;
  }

This syntax has the following inconveniences:

1) it's not clear at all that s is in fact an out *parameter* rather
than a regular local variable with some fancy attribute

2) it doesn't enforce the fact that s *must* be returned

3) it might let the programmer think it's possible to have more than one
"anystate" variable

4) the presence of the anystate variable is not exposed in the interface
(it's in the function definition but not in the declaration) so it might
not be available to the caller.

Point 4 is the most interesting. While it might be considered an
advantage (in the end, it should just be an implementation detail of
function foo), this makes it difficult if not impossible to implement
the feature! Yes, because the caller *must* pass in some way to foo()
some information about the need (or lack of) to construct the variable.
As the request of this information is not advertised in the declaration,
the compiler can't help but producing such information in *every*
function call. This is a two-fold problem: it violates the rule "don't
pay for what you don't need" and it will probably break all existing ABIs.

Just my opinion,

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: "jose.diego@gmail.com" <jose.diego@gmail.com>
Date: Wed, 18 Apr 2007 11:16:47 CST
Raw View
On Apr 16, 5:07 am, Greg Herlihy <gre...@pacbell.net> wrote:
> On 4/12/07 6:21 PM, in article
> 1176422460.558589.322...@y80g2000hsf.googlegroups.com, "Mathias Gaunard"
>
>
>
> <loufo...@gmail.com> wrote:
> > Here is a crazy idea that I just came up with.
>
> > I was thinking of the issue caused by the unneeded temporaries that
> > happened when returning std::string by value.
>
> > std::string foo()
> > {
> >     std::string s;
> >     /* some work on s */
> >     return s;
> > }
>
> > std::string s = foo(); // with a smart compiler doing NRVO, no
> > unneeded copy, construction or destruction
> > s = foo(); // constructs a tempory, calls s.operator=, then destructs
> > the temporary
>
> The "named return value optimization" (NRVO) can eliminate the temporary in
> the second example as well. Specifically, the NRVO optimization eliminates
> the need for a temporary by extending the lifetime of the local variable
> that foo() returns to be just as long as the lifetime of the temporary that
> foo() would have ordinarily returned. In other words, the local variable
> that foo() returns - and the temporary that holds foo()'s result (and whose
> contents are copied into "s") - are one and the same.
>
> > A possible solution would simply to write the function that way so
> > that another string could be reused:
>
> > void foo(std::string& s)
> > {
> >    s = ""; // to make it empty and forget about the old contents
> >    /* some work on s */
> > }
>
> This interface for foo() is inconvenient (and inefficient) whenever the
> value to be transformed is either const or otherwise needs to be preserved.
> A more convenient interface for foo() would separate input from output - and
> would accept input by const reference as produce output by return value. And
> thanks to the NRVO, the more convenient interface could well be the more
> efficient interface as well.

OTOH it is very efficient when we want to reuse the string storage.
std::getline() is a good example of that

Diego

---
[ 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: Mathias Gaunard <loufoque@gmail.com>
Date: Thu, 19 Apr 2007 08:08:20 CST
Raw View
On 17 avr, 22:43, AlbertoBarb...@libero.it (Alberto Ganesh Barbati)
wrote:

> 4) the presence of the anystate variable is not exposed in the interface
> (it's in the function definition but not in the declaration) so it might
> not be available to the caller.
>
> Point 4 is the most interesting. While it might be considered an
> advantage (in the end, it should just be an implementation detail of
> function foo), this makes it difficult if not impossible to implement
> the feature! Yes, because the caller *must* pass in some way to foo()
> some information about the need (or lack of) to construct the variable.

Indeed, so the function should be qualified specifically also.
Anyway, that's just a crazy idea, it lacks form.


---
[ 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: Mathias Gaunard <loufoque@gmail.com>
Date: Thu, 19 Apr 2007 08:07:53 CST
Raw View
On 19 avr, 02:16, "jose.di...@gmail.com" <jose.di...@gmail.com> wrote:
>
> OTOH it is very efficient when we want to reuse the string storage.
> std::getline() is a good example of that

Very good point.
A function returning a string in a loop would free and allocate new
storage everytime.


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