Move semantics for std::string?

I'm using C++03 and would love some way to apply move semantics to a std::string. Can boost facilitate this in some way without using smart pointers? Consider an example like below (This is a contrived example, so assume NRVO does not apply): std::string GetInformation( int someNumber ) { // We use 'someNumber' to look up a string std::string myValue( "hello world" ); // Create the string here return myValue; } Above, the return value would result in a copy, I'd like to move it instead. --------- Robert Dailey

On Thu, Feb 16, 2012 at 2:40 PM, Robert Dailey <rcdailey@gmail.com> wrote:
I'm using C++03 and would love some way to apply move semantics to a std::string. Can boost facilitate this in some way without using smart pointers? Consider an example like below (This is a contrived example, so assume NRVO does not apply):
std::string GetInformation( int someNumber ) { // We use 'someNumber' to look up a string std::string myValue( "hello world" ); // Create the string here return myValue; }
Above, the return value would result in a copy, I'd like to move it instead.
Well I think you can always make NRVO apply if you're always returning the same variable, which is always possible: just swap what you would otherwise return into that common variable. In general, though, no, I don't think you can cleanly introduce (emulated) move semantics non-intrusively in C++03. - Jeff

On Thu, Feb 16, 2012 at 5:01 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Thu, Feb 16, 2012 at 2:40 PM, Robert Dailey <rcdailey@gmail.com> wrote:
I'm using C++03 and would love some way to apply move semantics to a std::string. Can boost facilitate this in some way without using smart pointers? Consider an example like below (This is a contrived example, so assume NRVO does not apply):
std::string GetInformation( int someNumber ) { // We use 'someNumber' to look up a string std::string myValue( "hello world" ); // Create the string here return myValue; }
Above, the return value would result in a copy, I'd like to move it instead.
Well I think you can always make NRVO apply if you're always returning the same variable, which is always possible: just swap what you would otherwise return into that common variable.
In general, though, no, I don't think you can cleanly introduce (emulated) move semantics non-intrusively in C++03.
Just to be clear, what "common variable" are you referring to? Thanks for your answers.

On Thu, Feb 16, 2012 at 3:06 PM, Robert Dailey <rcdailey@gmail.com> wrote:
On Thu, Feb 16, 2012 at 5:01 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Thu, Feb 16, 2012 at 2:40 PM, Robert Dailey <rcdailey@gmail.com> wrote:
I'm using C++03 and would love some way to apply move semantics to a std::string. Can boost facilitate this in some way without using smart pointers? Consider an example like below (This is a contrived example, so assume NRVO does not apply):
std::string GetInformation( int someNumber ) { // We use 'someNumber' to look up a string std::string myValue( "hello world" ); // Create the string here return myValue; }
Above, the return value would result in a copy, I'd like to move it instead.
Well I think you can always make NRVO apply if you're always returning the same variable, which is always possible: just swap what you would otherwise return into that common variable.
In general, though, no, I don't think you can cleanly introduce (emulated) move semantics non-intrusively in C++03.
Just to be clear, what "common variable" are you referring to?
Thanks for your answers.
std::string foo() { std::string result; /*...*/ // would like to "return x;", but instead... result.swap(x); return result; /*...*/ // would like to "return y;", but instead... result.swap(y); return result; } - Jeff

2012/2/17 Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com>
std::string foo() { std::string result; /*...*/ // would like to "return x;", but instead... result.swap(x); return result; /*...*/ // would like to "return y;", but instead... result.swap(y); return result; }
Simplified RVO rules: If all return statements in a function refer to the same local variable OR if a function returns an ravlue in all cases, the copy can (and in practice will) be elided. // RVO-enabled: always returns the same local variable. string foo() { string res; if (flag) { res = "hello"; return res; } else { res = "bye"; return res; } } // RVO-enabled: always returns a temporary. string foo() { if (flag) return "hello"; else return "bye"; } It's a good practice to make all functions you write RVO-enabled. Roman Perepelitsa.

On Fri, Feb 17, 2012 at 1:11 AM, Roman Perepelitsa < roman.perepelitsa@gmail.com> wrote:
2012/2/17 Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com>
std::string foo() { std::string result; /*...*/ // would like to "return x;", but instead... result.swap(x); return result; /*...*/ // would like to "return y;", but instead... result.swap(y); return result; }
Simplified RVO rules: If all return statements in a function refer to the same local variable OR if a function returns an ravlue in all cases, the copy can (and in practice will) be elided.
// RVO-enabled: always returns the same local variable. string foo() { string res; if (flag) { res = "hello"; return res; } else { res = "bye"; return res; } }
// RVO-enabled: always returns a temporary. string foo() { if (flag) return "hello"; else return "bye"; }
It's a good practice to make all functions you write RVO-enabled.
So all of these functions are functionally equivalent to simply constructing a std::string object in the calling scope?

2012/2/17 Robert Dailey <rcdailey@gmail.com>
Simplified RVO rules: If all return statements in a function refer to the same local variable OR if a function returns an ravlue in all cases, the copy can (and in practice will) be elided.
// RVO-enabled: always returns the same local variable. string foo() { string res; if (flag) { res = "hello"; return res; } else { res = "bye"; return res; } }
// RVO-enabled: always returns a temporary. string foo() { if (flag) return "hello"; else return "bye"; }
It's a good practice to make all functions you write RVO-enabled.
So all of these functions are functionally equivalent to simply constructing a std::string object in the calling scope?
Yes.

On Thu, Feb 16, 2012 at 11:30 PM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Thu, Feb 16, 2012 at 3:06 PM, Robert Dailey <rcdailey@gmail.com> wrote:
On Thu, Feb 16, 2012 at 5:01 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
Well I think you can always make NRVO apply if you're always returning
the
same variable, which is always possible: just swap what you would otherwise return into that common variable.
In general, though, no, I don't think you can cleanly introduce (emulated) move semantics non-intrusively in C++03.
Just to be clear, what "common variable" are you referring to?
Thanks for your answers.
std::string foo() { std::string result; /*...*/ // would like to "return x;", but instead... result.swap(x); return result; /*...*/ // would like to "return y;", but instead... result.swap(y); return result; }
I think this is the simplest "move emulation" in C++03, which simply encapsulates the pattern above: template<class Swappable> Swappable move(Swappable& x) { Swappable result; // Also requires DefaultConstructible using std::swap; swap(x, result); return result; // NRVO } Usage: std::string foo() { std::string result; /*...*/ // would like to "return x;", but instead... return move(x); /*...*/ // would like to "return y;", but instead... return move(y); } Note that it is sematically different from std::move as it will always modify the argument, while std::move is similar to a cast to rvalue reference. HTH, -- gpd

On Fri, Feb 17, 2012 at 1:30 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Thu, Feb 16, 2012 at 3:06 PM, Robert Dailey <rcdailey@gmail.com> wrote:
On Thu, Feb 16, 2012 at 5:01 PM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Thu, Feb 16, 2012 at 2:40 PM, Robert Dailey <rcdailey@gmail.com> wrote:
I'm using C++03 and would love some way to apply move semantics to a std::string. Can boost facilitate this in some way without using smart pointers? Consider an example like below (This is a contrived example, so assume NRVO does not apply):
std::string GetInformation( int someNumber ) { // We use 'someNumber' to look up a string std::string myValue( "hello world" ); // Create the string here return myValue; }
Above, the return value would result in a copy, I'd like to move it instead.
Well I think you can always make NRVO apply if you're always returning the same variable, which is always possible: just swap what you would otherwise return into that common variable.
In general, though, no, I don't think you can cleanly introduce (emulated) move semantics non-intrusively in C++03.
Just to be clear, what "common variable" are you referring to?
Thanks for your answers.
std::string foo() { std::string result; /*...*/ // would like to "return x;", but instead... result.swap(x); return result; /*...*/ // would like to "return y;", but instead... result.swap(y); return result; }
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Or, if you're willing to count on your compiler's brains, you could avoid the common variable: template <typename T> inline T swapped(T& x) { T res; swap(x, res); return res; } string f() { [...] // res.swap(x); // return res; return swapped(x); } Note that in either case, this only avoids the copy from the return-statement expression to the return-value. What happens with the returned string-temporary in the context of the caller is a different issue. If you use it to construct another string, RVO will usually kick in. However, anything else is likely to introduce a superfluous copy, or something similiar. For example, assigning it to a string, passing it to a function taking a 'const string&', and so on... There has been a discussion not so long ago about rvalue emulation in C++03, which seems to have faded away. I proposed a method there for non-intrusive rvalue-ref emulation, with an example of how it can be used to avoid excessive temporaries for string concatenation. Depending on what you're actually trying to acheive, you might find this interesting: [http://lists.boost.org/Archives/boost/2012/02/190102.php] -- Dan
participants (5)
-
Dan Ivy
-
Giovanni Piero Deretta
-
Jeffrey Lee Hellrung, Jr.
-
Robert Dailey
-
Roman Perepelitsa