
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community. In c++03 I would pass almost everything by const& unless it was to be modified. This results in extra copies any time a temporary is passed. In c++11 I would pass anything that I plan on 'storing' or 'consuming' by &&. This results in the most efficient code, but 'breaks' lvalue compatibility and forces me to consider having two (or more) versions of every method. Unfortunately, you get a explosion of permutations of rvalue and const& as the number of arguments increases and it makes getting function pointers much more 'ugly'. Instead of providing two (or more) overloads, one for lvalues and one for rvalue, I have decided to only provide the rvalue overload and if the user wants to pass an lvalue they wrap with std::ref(), std::cref(), std::move() or my own helper copy() which makes the copy explicit and converts the lvalue to a rvalue. (std::ref() and std::cref() could only work if the arguments are template parameters... in which case the method would probably use std::forward<>() to handle the auto-detection of move vs copy semantics. template<typename T> T copy( const T& v ) { return v; } If I am writing a method that does not 'store' or 'consume' the input then I use const& As rvalue references are quite new, this 'convention' may be unexpected by users. How would you feel about using an API that assumed move semantics unless you explicitly specify copy or reference semantics? Is there any reason that there shouldn't be a boost::copy() in boost/utility for use in this situation? Are there some down sides to this approach that I am missing? In my experience 90% of functions that take std::string() end up using a temporary and 90% of strings are 'calculated', 'used', and 'forgotten', yet most methods take const& and result in a temporary value. I should probably clarify, that I would use const& for any types that do not benefit from move semantics (no deep copies). But when you are writing template code, you do not want to make that assumption about the type. Another practice I am considering is making certain classes 'explicit copy only'. template<typename T> T copy( const T& t ) { return t; } class test { public: test(){...}; test( test&& t ){...} private: template<typename T> friend T copy(const T&t); test& operator=(const test&); // not implemented test( const test& t ){...} std::vector<char> large_data; }; int main( int argc, char** argv ) { test x; test y = copy(x); test z = x; // error, test(const test&) is private... return 0; } I would use this for any class that contains any 'movable members', such a strings, vectors, maps, etc. Technically there is no reason why I couldn't copy them, but why shouldn't I attempt move semantics everywhere possible unless I really do want to copy? With implicit copies there is no way for the compiler to warn me that I am doing something potentially expensive. If it didn't break backward compatibility I would suggest that all of the standard containers adopt an explicit copy or move syntax or at least have a compiler flag to 'enable/disable' implicit copying for 'testing purposes'. Perhaps we could put them in a different namespace for those of us that want to disable implicit copying of deep data types, ie: xc::vector<>, xc::string, etc. Are these sane conventions? What could go wrong? I am I abusing rvalue references?

On Sat, Jun 9, 2012 at 9:21 PM, Daniel Larimer <dlarimer@gmail.com> wrote:
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community.
In c++03 I would pass almost everything by const& unless it was to be modified. This results in extra copies any time a temporary is passed.
In c++11 I would pass anything that I plan on 'storing' or 'consuming' by &&. This results in the most efficient code, but 'breaks' lvalue compatibility and forces me to consider having two (or more) versions of every method. Unfortunately, you get a explosion of permutations of rvalue and const& as the number of arguments increases and it makes getting function pointers much more 'ugly'.
Instead of providing two (or more) overloads, one for lvalues and one for rvalue, I have decided to only provide the rvalue overload and if the user wants to pass an lvalue they wrap with std::ref(), std::cref(), std::move() or my own helper copy() which makes the copy explicit and converts the lvalue to a rvalue. (std::ref() and std::cref() could only work if the arguments are template parameters... in which case the method would probably use std::forward<>() to handle the auto-detection of move vs copy semantics.
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload. -- gpd

On Jun 9, 2012, at 4:49 PM, Giovanni Piero Deretta wrote:
On Sat, Jun 9, 2012 at 9:21 PM, Daniel Larimer <dlarimer@gmail.com> wrote:
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community.
In c++11 I would pass anything that I plan on 'storing' or 'consuming' by &&. This results in the most efficient code, but 'breaks' lvalue compatibility and forces me to consider having two (or more) versions of every method. Unfortunately, you get a explosion of permutations of rvalue and const& as the number of arguments increases and it makes getting function pointers much more 'ugly'.
Instead of providing two (or more) overloads, one for lvalues and one for rvalue, I have decided to only provide the rvalue overload and if the user wants to pass an lvalue they wrap with std::ref(), std::cref(), std::move() or my own helper copy() which makes the copy explicit and converts the lvalue to a rvalue. (std::ref() and std::cref() could only work if the arguments are template parameters... in which case the method would probably use std::forward<>() to handle the auto-detection of move vs copy semantics.
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
- I only partially grasped the article the first time I read it (before posting my original message).... but in light your response I revisited it to see what I missed and you are right. Pass by value does almost exactly what I want *except* that copies are still implicit and I might accidentally 'copy' a large object when I didn't intend to. I would never know this without profiling.
So, how much value is there to 'explicit copy only' types?

On Jun 9, 2012, at 6:17 PM, Daniel Larimer wrote:
So, how much value is there to 'explicit copy only' types?
If you want to your type to be copyable, but you also want to be able to monitor where it is getting copied unnecessarily, one approach is to give it traditional copy syntax, but temporarily disable that copy when you want to review: inspect whatever doesn't compile to see if you really want to be making a copy there. This technique is how I monitored the cost of std::list::size() in C++03: I just commented out std::list::size(), recompiled and observed what broke. Then fixed those places that were assuming that std::list::size() was O(1). Howard

On Jun 9, 2012, at 6:43 PM, Howard Hinnant wrote:
On Jun 9, 2012, at 6:17 PM, Daniel Larimer wrote:
So, how much value is there to 'explicit copy only' types?
If you want to your type to be copyable, but you also want to be able to monitor where it is getting copied unnecessarily, one approach is to give it traditional copy syntax, but temporarily disable that copy when you want to review: inspect whatever doesn't compile to see if you really want to be making a copy there.
This technique is how I monitored the cost of std::list::size() in C++03: I just commented out std::list::size(), recompiled and observed what broke. Then fixed those places that were assuming that std::list::size() was O(1).
Howard
This is what I had been doing, but the side effect is that the copy is not always *visible* in the code. Often times I would find a copy being made indirectly that I wanted to 'keep', but it was impossible to 'search' the code for it.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 09/06/2012 22:49, Giovanni Piero Deretta wrote:
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
That is not true. This technique only applies if you need to make a copy at an arbitrary place, not in a particular subobject.

On Sun, Jun 10, 2012 at 3:24 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 09/06/2012 22:49, Giovanni Piero Deretta wrote:
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
That is not true. This technique only applies if you need to make a copy at an arbitrary place, not in a particular subobject.
Apart from the fact that "an arbitrary place" in your sentence would seem to cover anything, to what subobject are you referring to? The only thing I can think of is assignment operators of derived classes that need to forward to base classes. In that case I agree that pass by value does not work very well (I usually still use pass by value, but implement operator= in term of swap, which forwards to the base class swap). -- gpd

On 11/06/2012 13:14, Giovanni Piero Deretta wrote:
Apart from the fact that "an arbitrary place" in your sentence would seem to cover anything
You don't get to choose where. The compiler does.
to what subobject are you referring to?
Any subobject. Or any specific storage really.
The only thing I can think of is assignment operators of derived classes that need to forward to base classes. In that case I agree that pass by value does not work very well (I usually still use pass by value, but implement operator= in term of swap, which forwards to the base class swap).
According to this rule, I should pass by value whenever I want to copy the variable anyway. template<class T> struct foo { T t; foo(T t_) : t(t_) {} }; Clearly we can see this code causes one copy with rvalues, two with lvalues, instead of always one if we used const-reference. The only instance where this might be useful is operator=, and then again, it's probably still a bad idea. I had already pointed out to Dave that the way the rule as worded was incorrect.

On Mon, Jun 11, 2012 at 1:22 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
According to this rule, I should pass by value whenever I want to copy the variable anyway.
template<class T> struct foo { T t; foo(T t_) : t(t_) {} };
Shouldn't you use std::move here to ensure t_ is moved into t (if possible)?
Clearly we can see this code causes one copy with rvalues, two with lvalues, instead of always one if we used const-reference.
The only instance where this might be useful is operator=, and then again, it's probably still a bad idea.
-- Olaf

Mathias Gaunard wrote:
According to this rule, I should pass by value whenever I want to copy the variable anyway.
template<class T> struct foo { T t; foo(T t_) : t(t_) {} };
t( std::move( t_ ) ). In this case you can also std::forward, of course, this being a textbook example of forwarding, but then everything becomes convertible to foo, enter enable_if, and so on.

on Mon Jun 11 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 11/06/2012 13:14, Giovanni Piero Deretta wrote:
The only thing I can think of is assignment operators of derived classes that need to forward to base classes. In that case I agree that pass by value does not work very well (I usually still use pass by value, but implement operator= in term of swap, which forwards to the base class swap).
According to this rule, I should pass by value whenever I want to copy the variable anyway.
template<class T> struct foo { T t; foo(T t_) : t(t_) {} };
Clearly we can see this code causes one copy with rvalues, two with lvalues, instead of always one if we used const-reference.
That's because you wrote it wrong. It should be foo(T t_) : t(std::move(t_)) {}
The only instance where this might be useful is operator=, and then again, it's probably still a bad idea.
I had already pointed out to Dave that the way the rule as worded was incorrect.
? you did? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 06/12/2012 06:05 PM, Dave Abrahams wrote:
That's because you wrote it wrong. It should be
foo(T t_) : t(std::move(t_)) {}
That does one copy plus one move for lvalues, while a single copy would have been enough with foo(T const& t_) : t(t_) {} There is no point in the pass-by-value to elide copies with rvalues technique at all in C++11 anyway. The only uses it could have were limited to C++03.
I had already pointed out to Dave that the way the rule as worded was incorrect.
? you did?
<http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/comment-page-1/#comment-82>

Mathias Gaunard wrote:
On 06/12/2012 06:05 PM, Dave Abrahams wrote:
That's because you wrote it wrong. It should be
foo(T t_) : t(std::move(t_)) {}
That does one copy plus one move for lvalues, while a single copy would have been enough with
foo(T const& t_) : t(t_) {}
That, however, does a copy for rvalues, too.

Mathias Gaunard wrote:
On 12/06/2012 22:54, Peter Dimov wrote:
Mathias Gaunard wrote:
foo(T const& t_) : t(t_) {}
That, however, does a copy for rvalues, too.
Yes, the solution to optimize rvalues is to addd an rvalue reference overload, but that's beside the point.
Or 2^N overloads, if there's more than one argument to consume.

On 06/13/2012 04:12 PM, Peter Dimov wrote:
Or 2^N overloads, if there's more than one argument to consume.
In which case, make your constructor a template so that all those overloads get generated through template instantiation, making use of the template type resolution mechanism specifically designed for perfect forwarding.

On 12 June 2012 18:08, Ion Gaztañaga <igaztanaga@gmail.com> wrote:
If I modify my implementation because I no longer need the internal copy (e.g. the copy was required by an internal function/helper function), I can't optimize the code and change the signature of the function to take a reference, as name mangling changes and I'll need to recompile the caller. If I offer both lvalue and rvalue reference variants I type a bit more but I can safely change the implementation.
On 13 June 2012 12:48, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 06/13/2012 04:12 PM, Peter Dimov wrote:
Or 2^N overloads, if there's more than one argument to consume.
In which case, make your constructor a template so that all those overloads get generated through template instantiation, making use of the template type resolution mechanism specifically designed for perfect forwarding.
But if your constructor is a template, that code resides in the header, so don't you end up recompiling the caller anyway? -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

(i know i have been advocating pass-by-value, but....) On 13/giu/2012, at 19.41, Nevin Liber <nevin@eviloverlord.com> wrote:
On 12 June 2012 18:08, Ion Gaztañaga <igaztanaga@gmail.com> wrote:
If I modify my implementation because I no longer need the internal copy (e.g. the copy was required by an internal function/helper function), I can't optimize the code and change the signature of the function to take a reference, as name mangling changes and I'll need to recompile the caller. If I offer both lvalue and rvalue reference variants I type a bit more but I can safely change the implementation.
On 13 June 2012 12:48, Mathias Gaunard <mathias.gaunard@ens- lyon.org> wrote:
On 06/13/2012 04:12 PM, Peter Dimov wrote:
Or 2^N overloads, if there's more than one argument to consume.
In which case, make your constructor a template so that all those overloads get generated through template instantiation, making use of the template type resolution mechanism specifically designed for perfect forwarding.
But if your constructor is a template, that code resides in the header, so don't you end up recompiling the caller anyway?
You can have a thin template forwarding to a single externally compiled implementation using for example rvalue references for all parameters. The template would copy or move depending on the actual parameter type. -- gpd

On 13 June 2012 14:44, Gpderetta <gpderetta@gmail.com> wrote:
You can have a thin template forwarding to a single externally compiled implementation using for example rvalue references for all parameters. The template would copy or move depending on the actual parameter type.
So we've moved from 1 function to 2N+1 functions. I also don't quite see how this will work with member initializers, as I don't want to do construct-then-assign. -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

On 13/06/2012 22:43, Nevin Liber wrote:
On 13 June 2012 14:44, Gpderetta<gpderetta@gmail.com> wrote:
You can have a thin template forwarding to a single externally compiled implementation using for example rvalue references for all parameters. The template would copy or move depending on the actual parameter type.
So we've moved from 1 function to 2N+1 functions. I also don't quite see how this will work with member initializers, as I don't want to do construct-then-assign.
There is no magic. If you want different code fro 2^n cases, you need to have 2^n functions. You can generate them through a sngle template function, or you can write them all by hand.

El 09/06/2012 22:49, Giovanni Piero Deretta escribió:
On Sat, Jun 9, 2012 at 9:21 PM, Daniel Larimer<dlarimer@gmail.com> wrote:
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community.
In c++03 I would pass almost everything by const& unless it was to be modified. This results in extra copies any time a temporary is passed.
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
What do you mean by "consume"? Passing by value is good if you are going to construct a new object in your implementation. If you want to reuse resources of the passed object (memory from std::string, already constructed objects from a container...) passing by reference is the best choice. If you want to reuse resources from "*this", passing a const reference is the best way: implementing vector::operator=() with pass by value would be a terrible idea IMHO. You can catch temporaries by rvalue references to reuse external resources. For generic code, catching by value could do some premature pessimization. Passing by value has also another downside: it makes your binary interface dependent on the function implementation (do I copy the parameter?). If I change the implementation I need to break ABI. I'm really worried about "pass by value is free" and "return by value is free" statements I'm hearing in some C++11 panels. Ion ************************************************************** A bit off-topic: language extension to achieve maximum efficiency ************************************************************** When thinking in solutions to this pass by value/reference issues, I feel C++ is missing some language feature so that a function can detect (at runtime, avoiding instantiations) if the output parameter is already constructed. Since function signature must unique, the caller should pass that information to the function in runtime. The syntax to write generic code with N (possibly constructed) parameters is not an easy task. For output parameters (I haven't come with a good syntax for input parameters), we could expand NRVO experience: We can pass the state of the output parameter in the lower bit of the address (if objects are aligned, although it might interfere with common optimizations like encoding rbtree color in the lower bit of the parent pointer) or a hidden additional parameters using a bitset (a bitset might hold 32/64 states and it's calculated at compile time in the caller side). This syntax also allows multiple return types. Say: void function ( A &a default(1) //return parameters or output references , B &b default{2, 9} , C &c default(b,c) , int a //normal parameter ) multireturn //or something that tells the compiler //"this function takes implicit bitset" //that indicates if "default" constructors //must be called. Maybe it could be //detected from "default". { //a, b, & c are in indeterminate state (they might be //copies of already constructed output parameters or //constructed with default syntax so that RVO is applied. //a, b & c might reuse internal memory a = ... b = ... c = ... } Usage: //RVO is used for all parameters //default initialization syntax used //inside "function" [A a; B b; C c] = function(a, b, c, 0); A a; a = ... //RVO for b & c, output reference //for a [B b; C c] = function(a, b, c, 0); //RVO is used for a copy elision for b //default initialization syntax used //inside "function" [A a; B b; C c] = function(a, b, c, 0); I think this might have issues with exception handling, but I think RVO already has these problems as the copy elision might avoid a copy exception when returning an object. Function overload might be also very complicated (although we could consider return types as non-const references). Function pointers and pointer to members could also be affected (an extra hidden parameter is needed). For input parameters things are more complicated. Say: void function ( mutable const A &a ) //const input parameter or copy Depending on a runtime value, we can modify the source (a rvalue was catched as const reference) or not (a lvalue was catched). Think about it as a runtime alternative to the templated perfect forwarding (T &&t) alternative: void function (mutable const A &a ) //const input parameter or copy { //A rvalue was catched, we can modify 'a' if(mutable(a)){ this->a_.swap(a); } //Passed by const-reference 'a' is immutable else { this->a_ = a; } } To achieve some basic safety, we need help from the compiler: 'a 'can't be used as non-const if code is not placed inside a mutable scope: void function (mutable const A &a ) //const input parameter or copy { //Ok, read operations and const member functions //can be called anywhere b = a n = a.size() } if(mutable(a, x...)){ //Ok, a is modified only when it's mutable this->a_.swap(a); } //... { //Compilation error: non-const member function. a.clear(); //Compilation error: used as non-const reference. modify_a(a); }

On 10/06/2012 22:38, Ion Gaztañaga wrote:
When thinking in solutions to this pass by value/reference issues, I feel C++ is missing some language feature so that a function can detect (at runtime, avoiding instantiations) if the output parameter is already constructed.
An output parameter is never constructed. This is important for exception safety.
Usage:
//RVO is used for all parameters //default initialization syntax used //inside "function" [A a; B b; C c] = function(a, b, c, 0);
Your best bet is probably to use expressions templates so that A a; B b; tie(a, b) = function(c, 0); is evaluated as a function that takes inputs and outputs.

El 11/06/2012 13:02, Mathias Gaunard escribió:
On 10/06/2012 22:38, Ion Gaztañaga wrote:
When thinking in solutions to this pass by value/reference issues, I feel C++ is missing some language feature so that a function can detect (at runtime, avoiding instantiations) if the output parameter is already constructed.
An output parameter is never constructed. This is important for exception safety.
Ok, then a non-const reference is an input-output parameter, I agree. The issue is that we can't generate an optimal "func()" for : A a; a =... a = func() and A a(func()); with the same "func()" definition. Inside func() we can't know if the "output" value is going to be assigned to an already constructed object or it will be used for copy-construction (with NRVO, in-place construction). If it's going to be assigned, I want to reuse a's resources as they are going to be discarded anyway. To get optimal code I need to write two functions: //function to construct from scratch using NRVO A a(func_factory()); //function to modify A reusing its resources. A a; func_modify(a); In C++03, func_modify() would be the choice of performance-conscious programmers. In C++11, as we've told that "return by value is free" and the syntax is more elegant, I'm afraid everyone will write "func_factory". And func_factory() is less efficient when used in loops and other situations where resource reusing is essential. Regarding object construction order, NRVO makes some interesting things. Say: A func(A a3) { a3.modify(); return a3; } A a2 = func(A()); A() could be constructed in &a2 and a3 could be an alias for a2. The return value could be already constructed before func() is called! Let's think about a more "return like" syntax for multiple output parameters: //Declaration A, B func(size_t num_elements); //Definition A a default(1, 2, 3), B b default(4,5) factory(size_t num_elements) //a & b are always constructed before function arguments //if not externally constructed (expression was in an assignment) //the default construction expression is used { //a is a container, if a is already constructed, we don't //destroy elements a.resize(num_elements); for(size_t i = 0, max = a.size(); i != max; ++i){ a[i] = ...; } //b is a string, if a is already constructed, reuse memory b = "abcdef"; //implicit return of a & b } I don't see any problem with exception safety. If in runtime "factory()" needs to construct a and b, the compiler can track it, just as I could use placement new to construct them in my code inside an "if" condition. So I could write: A a; a = ... //b is copy constructed, a is assigned and resources where reused [B b, a] = factory(); I agree this feature is very tricky, but I can't find any mechanism to obtain optimal code with a single function. For single argument functions you could provide two functions: void reuse(A &a); A factory() { A a; reuse(a); } when the number of output parameters grow, then you need a lot of overloads for each combination. Forgive me if this was too off-topic, this is just an obsession I have with C++ output parameters! Best, Ion

In C++03, func_modify() would be the choice of performance-conscious programmers. In C++11, as we've told that "return by value is free" and the syntax is more elegant, I'm afraid everyone will write "func_factory". And func_factory() is less efficient when used in loops and other situations where resource reusing is essential.
If you aren't in a loop you probably don't care about performance. I know I intend to stick with pass by reference. It is very useful to clearly understand and be able to easily reason about the ownership of resources in a program. Get the ownership of the resource and the construction of your object in the same place as much as possible and apply RAII and you have the software design problem solved. Everyone who doesn't own the resources sees a reference to the object. Return by value is supposed to be easier to reason about than pass by reference, but I never had trouble reasoning about my code that passes by reference. If your func_factory() is a template then it needs to understand how to construct its output type and it can't infer its output type from the input arguments in most cases. In contrast func_modify doesn't need to know how to construct the output type and can infer it. You can solve these problems with func_factory using expression templates, but then you might just as well pass the left hand side of the assignment operator by reference when evaluating the expression template. What the new language features do in my view isn't to change the language so that we always return by value and transfer ownership of resources around willy-nilly because it's "free", but to make it less expensive when our design intent really is to transfer ownership. Moving something from one container to another is a great example of a place where the intent really is to transfer ownership. We still pass containers by ref and use iterators. Sometimes one wants an accumulate semantic. In Sean Parent's own words reference semantics are unavoidable. We need reference semantics and we should understand where, why and how to use them and reason about them. We might as well embrace reference semantics and make sure we are good at reasoning about them. Regards, Luke

on Mon Jun 11 2012, "Simonson, Lucanus J" <lucanus.j.simonson-AT-intel.com> wrote:
In C++03, func_modify() would be the choice of performance-conscious programmers. In C++11, as we've told that "return by value is free" and the syntax is more elegant, I'm afraid everyone will write "func_factory". And func_factory() is less efficient when used in loops and other situations where resource reusing is essential.
If you aren't in a loop you probably don't care about performance. I know I intend to stick with pass by reference. It is very useful to clearly understand and be able to easily reason about the ownership of resources in a program.
If that's your primary concern, why on earth wouldn't you use pass-by-value? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 06/12/2012 06:02 PM, Dave Abrahams wrote:
on Mon Jun 11 2012, "Simonson, Lucanus J"<lucanus.j.simonson-AT-intel.com> wrote:
In C++03, func_modify() would be the choice of performance-conscious programmers. In C++11, as we've told that "return by value is free" and the syntax is more elegant, I'm afraid everyone will write "func_factory". And func_factory() is less efficient when used in loops and other situations where resource reusing is essential.
If you aren't in a loop you probably don't care about performance. I know I intend to stick with pass by reference. It is very useful to clearly understand and be able to easily reason about the ownership of resources in a program.
If that's your primary concern, why on earth wouldn't you use pass-by-value?
On a slightly unrelated note, let me add that for fundamental types, pass-by-value is also performance critical when functions aren't inlined. In a loop, it is often very important to avoid going through the stack and to keep as much as possible in registers.

Dave Abrahams wrote:
If you aren't in a loop you probably don't care about performance. I know I intend to stick with pass by reference. It is very useful to clearly understand and be able to easily reason about the ownership of resources in a program.
If that's your primary concern, why on earth wouldn't you use pass-by-value?
Let's take a sort of extreme example: A a; mutate(a, b); //a passed by reference as in/out mutate(a, c); vs. A a; a = mutate_rvr(std::move(a), b); a = mutate_rvr(std::move(a), c); Here I compare an accumulate semantic with and without move semantics. Both make zero copies. The latter results in four moves of a while the former has zero moves of a. The former is less readable because you need to know that the first argument is the output. In my coding convention such functions are always named with a verb describing the action taken on the in/out parameter and the in/out is the first argument. A function that returns by value is named with a noun describing the return value. By convention I always know what is going on when I pass by reference for in/out parameters. The second allows equational reasoning, but composes the same since mutate returns a reference to A, again by my personal convention. mutate(mutate(a,b),c); a = mutate_rvr(mutate_rvr(std::move(a), b),c); I just don't find it easier to think about an interface that requires that I transfer ownership of an object into it so that it can modify the object then return it by value to transfer ownership back. The reason I don't find it easier is because it is unnecessary and error prone. It is very easy to forget to call move. A a; a = mutate_rvr(a, b); a = mutate_rvr(a, c); It will compile, function correctly passing tests, but it is now a performance bug. To catch these bugs I need to put a logger in the copy constructor/assignment operator and run a special test to audit move/copy behavior. (or make A a move only type, which seems draconian) I also find copy Ellison and RVO harder to reason about than reference semantics because it is more complex and less explicit in the code to figure out whether the optimizations will be applied. I would rather use std::move in the special cases where I no longer should have ownership of an object in the current scope because the design intent is to transfer that ownership somewhere else (into a container, for example). These are the places I am returning/passing by value in C++03. I don't know where to draw the line in changing coding style to make use of move semantics, but I don't think it should be drawn at either extreme, and I see very little downside to drawing it closer to the C++03 style that already works very well for me. There is no doubt that I would use move semantics everywhere that transfer of ownership is necessary and the performance advantage of move versus copy is beneficial. Everywhere else I'm inclined to continue to use references or make copies. We can do three things. We can copy, we can refer-to and we can transfer-ownership-of. There is plenty of occasion to need to do all three when programming. I would think that we should all just do whichever best fits our design intent in any given situation rather than try to prefer one over another. Regards, Luke

On 06/12/2012 07:51 PM, Simonson, Lucanus J wrote:
I also find copy Ellison and RVO harder to reason about than reference semantics because it is more complex and less explicit in the code to figure out whether the optimizations will be applied.
RVO is mostly an ABI issue. It always gets applied in non-ambiguous scenarios, it's not an optimization that depends on the mood of the compiler. For any non-POD type, values are passed by pointer. Likewise, when such types are returned by value, the function takes a pointer to storage suitable for that type. It constructs the value to return at that storage location. First optimization: calling a function that takes an argument by value with a temporary will directly pass the pointer to the temporary to that function. Second optimization: when calling a function that returns a value that is directly used to construct an object, the callee uses the storage for the object itself to construct it instead of constructing it in a temporary and copying it. All compilers implement those optimizations (even plain old ones like MSVC6). Now there is the NRVO optimization, which is slightly more tricky.

on Tue Jun 12 2012, "Simonson, Lucanus J" <lucanus.j.simonson-AT-intel.com> wrote:
Dave Abrahams wrote:
If you aren't in a loop you probably don't care about performance. I know I intend to stick with pass by reference. It is very useful to clearly understand and be able to easily reason about the ownership of resources in a program.
If that's your primary concern, why on earth wouldn't you use pass-by-value?
Let's take a sort of extreme example:
A a; mutate(a, b); //a passed by reference as in/out mutate(a, c);
vs.
A a; a = mutate_rvr(std::move(a), b); a = mutate_rvr(std::move(a), c);
Here I compare an accumulate semantic with and without move semantics. Both make zero copies. The latter results in four moves of a while the former has zero moves of a.
But that's not your primary concern.
The former is less readable because you need to know that the first argument is the output. In my coding convention such functions are always named with a verb describing the action taken on the in/out parameter and the in/out is the first argument. A function that returns by value is named with a noun describing the return value. By convention I always know what is going on when I pass by reference for in/out parameters. The second allows equational reasoning, but composes the same since mutate returns a reference to A, again by my personal convention.
But it doesn't guarantee no aliasing. a and b could turn out to be the same object, which means they share ownership of... whatever it is they own.
mutate(mutate(a,b),c);
a = mutate_rvr(mutate_rvr(std::move(a), b),c);
I just don't find it easier to think about an interface that requires that I transfer ownership of an object into it so that it can modify the object then return it by value to transfer ownership back.
That's the "wrong" way to think about it. You're not transferring ownership; you're computing new values. Even the names you use muddle this distinction. "mutate_rvr" says it's a logical mutation, when it isn't. It's a noun, like you said. So: const X d = compute(compute(a, b), c); is what you should start with, from the "thinking about it" point of view. Then you might do things like these a = compute(compute(move(a), b), c); ^ ^^^^^^^ as optimizations.
The reason I don't find it easier is because it is unnecessary and error prone. It is very easy to forget to call move.
Then performance is your concern, not eliminating the need to think about ownership.
A a; a = mutate_rvr(a, b); a = mutate_rvr(a, c);
It will compile, function correctly passing tests, but it is now a performance bug.
Hmm. A a; a = compute(a, b); a = compute(a, c); It would be nice if the compiler could insert those moves for us, wouldn't it?
To catch these bugs I need to put a logger in the copy constructor/assignment operator and run a special test to audit move/copy behavior. (or make A a move only type, which seems draconian)
I also find copy Ellison and RVO harder to reason about than reference semantics because it is more complex and less explicit in the code to figure out whether the optimizations will be applied.
I would rather use std::move in the special cases where I no longer should have ownership of an object in the current scope because the design intent is to transfer that ownership somewhere else (into a container, for example).
You know, I don't think of move in terms of ownership transfer unless unique_ptr is involved.
These are the places I am returning/passing by value in C++03. I don't know where to draw the line in changing coding style to make use of move semantics, but I don't think it should be drawn at either extreme, and I see very little downside to drawing it closer to the C++03 style that already works very well for me.
+1. Definitely do what works for you.
There is no doubt that I would use move semantics everywhere that transfer of ownership is necessary and the performance advantage of move versus copy is beneficial. Everywhere else I'm inclined to continue to use references or make copies. We can do three things. We can copy, we can refer-to and we can transfer-ownership-of. There is plenty of occasion to need to do all three when programming. I would think that we should all just do whichever best fits our design intent in any given situation rather than try to prefer one over another.
I hate to say this, because I agree with what you've said, but... "obviously." I get the sense you're arguing with the position of someone who isn't around this list at the moment. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 06/11/2012 09:21 PM, Ion Gaztañaga wrote:
If it's going to be assigned, I want to reuse a's resources
And that's the problem. Reusing those resources is destructive, so if your function fails before it returns the new value, the old value is lost. It is not natural for something written as foo = bar(); to change foo if bar fails.

El 12/06/2012 16:51, Mathias Gaunard escribió:
On 06/11/2012 09:21 PM, Ion Gaztañaga wrote:
If it's going to be assigned, I want to reuse a's resources
And that's the problem. Reusing those resources is destructive, so if your function fails before it returns the new value, the old value is lost.
It is not natural for something written as foo = bar(); to change foo if bar fails.
Thanks for pointing this, I was completely missing it. If the assignment syntax is confusing then the only choice not to surprise the programmer is to use reference passing syntax. Since we all agree that modify_bar(a); means that a could be left in an indeterminate state. Then the question is how can we make this optimal also with non-constructed objects. 1) Some NRVO, some modified B b; b =...; D d; d =...; //NRVO for a&c, mutable reference for b&d [A a, C c] -> modify_or_construct(a, b, c, d); 2) All modified //a,b,c,d modified modify_or_construct(a, b, c, d); 3) All constructed via NRVO to obtain strong exception guarantee (assume A, B, C, D's move constructors don't throw) //Might throw [A a2, B b2, C c2, D d2] -> modify_or_construct(a, b, c, d); //No-throw guarantee a = std::move(a2); b = std::move(b2); c = std::move(c2); d = std::move(d2); Best, Ion

on Tue Jun 12 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
It is not natural for something written as foo = bar(); to change foo if bar fails.
But you usually can't tell the difference between bar() failing and the assignment failing, and it's perfectly natural for a failed assignment to change the assignee. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 15/06/2012 06:42, Dave Abrahams wrote:
on Tue Jun 12 2012, Mathias Gaunard<mathias.gaunard-AT-ens-lyon.org> wrote:
It is not natural for something written as foo = bar(); to change foo if bar fails.
But you usually can't tell the difference between bar() failing and the assignment failing, and it's perfectly natural for a failed assignment to change the assignee.
I can tell perfectly fine with T foo; try { foo = bar(); } catch(...) { } // what state is foo in now?

On 15.06.2012 14:36, Mathias Gaunard wrote:
On 15/06/2012 06:42, Dave Abrahams wrote:
But you usually can't tell the difference between bar() failing and the assignment failing, and it's perfectly natural for a failed assignment to change the assignee.
I can tell perfectly fine with
T foo;
try { foo = bar(); } catch(...) { }
// what state is foo in now? Assume T is std::array<E, 32>, where E isn't movable and its copy constructor/assignment might throw. std::array's assignment operator gives only the basic guarantee. So if an exception occurred in the assignment operator, you know that the vector is array, but you don't know anything about its contents. It might be a wild mixture of what was in it before the assignment and the elements returned from bar.
Sebastian

On 15/06/2012 15:59, Sebastian Redl wrote:
Assume T is std::array<E, 32>, where E isn't movable and its copy constructor/assignment might throw. std::array's assignment operator gives only the basic guarantee. So if an exception occurred in the assignment operator, you know that the vector is array, but you don't know anything about its contents. It might be a wild mixture of what was in it before the assignment and the elements returned from bar.
Some operator= implementation do not provide the strong guarantee, but that's not the case of most objects. It doesn't seem a good idea to introduce a new function overloading mechanism to drop that would always void this guarantee.

on Fri Jun 15 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 15/06/2012 15:59, Sebastian Redl wrote:
Assume T is std::array<E, 32>, where E isn't movable and its copy constructor/assignment might throw. std::array's assignment operator gives only the basic guarantee. So if an exception occurred in the assignment operator, you know that the vector is array, but you don't know anything about its contents. It might be a wild mixture of what was in it before the assignment and the elements returned from bar.
Some operator= implementation do not provide the strong guarantee, but that's not the case of most objects.
Most people don't know what "most objects" are like :-)
It doesn't seem a good idea to introduce a new function overloading mechanism to drop that would always void this guarantee.
I don't understand this sentence. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 15/06/2012 18:02, Dave Abrahams wrote:
Most people don't know what "most objects" are like :-)
The copy and swap idiom is usually what's used for non-containers.
It doesn't seem a good idea to introduce a new function overloading mechanism to drop that would always void this guarantee.
I don't understand this sentence.
Some words were left when I was rewriting it. It doesn't seem a good idea to introduce a new function overloading mechanism that would always void this guarantee. This is referring to Ion's idea for a language extension.

El 15/06/2012 19:41, Mathias Gaunard escribió:
On 15/06/2012 18:02, Dave Abrahams wrote:
Most people don't know what "most objects" are like :-)
The copy and swap idiom is usually what's used for non-containers.
It doesn't seem a good idea to introduce a new function overloading mechanism to drop that would always void this guarantee.
I don't understand this sentence.
Some words were left when I was rewriting it.
It doesn't seem a good idea to introduce a new function overloading mechanism that would always void this guarantee.
I agree that is not desirable to weaken strong exception guarantees for objects because of the syntax. However there is an alternative syntax explained in: http://article.gmane.org/gmane.comp.lib.boost.devel/231570 that does not void this guarantee as already constructed parameters are passed like references. I don't think this should surprise the programmer: //A & B constructed, c & d reused C c(...); D d(...); [A a, B b] -> int ret = produce_abcd(a, b, c, d); Best, Ion

on Fri Jun 15 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 15/06/2012 06:42, Dave Abrahams wrote:
on Tue Jun 12 2012, Mathias Gaunard<mathias.gaunard-AT-ens-lyon.org> wrote:
It is not natural for something written as foo = bar(); to change foo if bar fails.
But you usually can't tell the difference between bar() failing and the assignment failing, and it's perfectly natural for a failed assignment to change the assignee.
I can tell perfectly fine with
T foo;
try { foo = bar(); } catch(...) { }
1. How can you tell whether bar failed or the assignment failed, here? 2. Do you really write code like that?
// what state is foo in now?
Exactly my question. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 15/06/2012 17:59, Dave Abrahams wrote:
1. How can you tell whether bar failed or the assignment failed, here?
If I know that T::operator= has the strong guarantee, I know that foo will always be in either of two states: either bar() succeeds, and it has the new value returned by bar(), or it failed, and it has the old value. If overloading were allowed to take foo, half-modify it, then fail, then that wouldn't be true anymore.
2. Do you really write code like that?
Of course, what would be the point of exceptions is not to catch them?

on Fri Jun 15 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 15/06/2012 17:59, Dave Abrahams wrote:
1. How can you tell whether bar failed or the assignment failed, here?
If I know that T::operator= has the strong guarantee,
Big if. That wasn't part of the scenario you framed.
I know that foo will always be in either of two states: either bar() succeeds, and it has the new value returned by bar(), or it failed, and it has the old value.
Yes, by definition.
If overloading were allowed to take foo, half-modify it, then fail, then that wouldn't be true anymore.
2. Do you really write code like that?
Of course, what would be the point of exceptions is not to catch them?
Usually you want to do something with the exception once caught; your code doesn't do that. And code where the catch block doesn't rethrow tends to be incredibly rare. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 6/16/2012 12:24 AM, Dave Abrahams wrote:
on Fri Jun 15 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 15/06/2012 17:59, Dave Abrahams wrote:
If overloading were allowed to take foo, half-modify it, then fail, then that wouldn't be true anymore.
2. Do you really write code like that? Of course, what would be the point of exceptions is not to catch them? Usually you want to do something with the exception once caught; your code doesn't do that. And code where the catch block doesn't rethrow tends to be incredibly rare.
I hope this isn't too OT, but this statement, although subjective, doesn't seem true to me: "... code where the catch block doesn't rethrow tends to be incredibly rare." Is there more context to this statement, or is that intended to be a general truth? If you're talking about writing a library then it seems natural that you want the users of that library to make decisions about how to handle exceptions, but OTOH I don't think you want to terminate an application every time an exception is thrown (do you?). Since this is a Boost mailing list you probably mean that _library_ code that isn't exception neutral is incredibly rare. That seems more true to me, but I would only add 'well-written' before library. Greg

on Fri Jun 15 2012, bibil <bibil.thaysose-AT-gmail.com> wrote:
I hope this isn't too OT, but this statement, although subjective, doesn't seem true to me:
"... code where the catch block doesn't rethrow tends to be incredibly rare."
Is there more context to this statement, or is that intended to be a general truth? If you're talking about writing a library then it seems natural that you want the users of that library to make decisions about how to handle exceptions, but OTOH I don't think you want to terminate an application every time an exception is thrown (do you?).
No, you usually don't. However, you generally want to limit "catch-and-swallow/catch-and-translate" blocks to a very few instances in the code.
Since this is a Boost mailing list you probably mean that _library_ code that isn't exception neutral is incredibly rare. That seems more true to me, but I would only add 'well-written' before library.
I feel "well-written" is redundant when making these sorts of unsupportably broad and sweeping generalizations ;-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 16/06/2012 06:24, Dave Abrahams wrote:
Of course, what would be the point of exceptions i[f] not to catch them?
Usually you want to do something with the exception once caught; your code doesn't do that. And code where the catch block doesn't rethrow tends to be incredibly rare.
My code was an example, of course real code would do something. There are a lot of valid cases where you can do something which doesn't involve setting a new value to foo or rethrowing.

On Jun 10, 2012, at 4:38 PM, Ion Gaztañaga wrote:
El 09/06/2012 22:49, Giovanni Piero Deretta escribió:
On Sat, Jun 9, 2012 at 9:21 PM, Daniel Larimer<dlarimer@gmail.com> wrote:
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community.
In c++03 I would pass almost everything by const& unless it was to be modified. This results in extra copies any time a temporary is passed.
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
What do you mean by "consume"? Passing by value is good if you are going to construct a new object in your implementation. If you want to reuse resources of the passed object (memory from std::string, already constructed objects from a container...) passing by reference is the best choice. If you want to reuse resources from "*this", passing a const reference is the best way: implementing vector::operator=() with pass by value would be a terrible idea IMHO. You can catch temporaries by rvalue references to reuse external resources. For generic code, catching by value could do some premature pessimization.
I mean that a common design pattern is.... create some object. set some parameters. pass it to some function. ... never use it again... The user code could look like: some_method( move(x) ) Or it could look like: some_method(x); // this version does not allow some_mehtod(x) to be called forcing 'move()' to be used. some_class::some_method( X&& x ) { this->member = move(x); } // this version means some_method(x) results in a hidden 'copy' unless the caller is 'smart enough' to do some_method(move(x)) to init the 'copy'. some-class::some_method( X x ) { this->member = move(x); } In the first case: some_method(move(x)) results in one move operation and it is explicit to the user that the object is 'going away'. In the second case, the object is first moved into the temporary and then moved into the member, but the caller is not aware of the move, because they know it is copied unless the explicitly say to move it. Moves are not free. A struct that has 10 members + a vector still has to 'copy' the other 10 members even if it can move the vector. This is where pass-by-value breaks down, I think. Dan

on Sun Jun 10 2012, Ion Gaztañaga <igaztanaga-AT-gmail.com> wrote:
El 09/06/2012 22:49, Giovanni Piero Deretta escribió:
On Sat, Jun 9, 2012 at 9:21 PM, Daniel Larimer<dlarimer@gmail.com> wrote:
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community.
In c++03 I would pass almost everything by const& unless it was to be modified. This results in extra copies any time a temporary is passed.
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
What do you mean by "consume"? Passing by value is good if you are going to construct a new object in your implementation.
Or if you need to write on a copy of the contents of the actual argument. That's what "consume" means.
If you want to reuse resources of the passed object (memory from std::string, already constructed objects from a container...) passing by reference is the best choice.
Passing by reference always defeats copy elision. Why would you want to do that?
If you want to reuse resources from "*this", passing a const reference is the best way: implementing vector::operator=() with pass by value would be a terrible idea IMHO.
Right, because there's a much more efficient way to do it.
You can catch temporaries by rvalue references to reuse external resources. For generic code, catching by value could do some premature pessimization.
Which pessimization is that?
Passing by value has also another downside: it makes your binary interface dependent on the function implementation (do I copy the parameter?). If I change the implementation I need to break ABI.
I don't see how that follows. Leave the ABI alone. Pass-by-value completely insulates the caller from the callee.
I'm really worried about "pass by value is free" and "return by value is free" statements I'm hearing in some C++11 panels.
Where are you hearing that? I've heard Scott Meyers complain about that too, but as far as I can tell, it's a misunderstanding of what's being said. [By the way "Want speed? Pass by value" is intended to be an attention-grabbing title that stands conventional wisdom on its head, not some sort of declaration that pass-by-value is always efficient. The point is that for years people have compulsively avoided passing and returning things by value for efficiency reasons, and it pays to understand where copy elision kicks in (which it does on all major compilers).]
************************************************************** A bit off-topic: language extension to achieve maximum efficiency **************************************************************
When thinking in solutions to this pass by value/reference issues, I feel C++ is missing some language feature so that a function can detect (at runtime, avoiding instantiations) if the output parameter is already constructed. Since function signature must unique, the caller should pass that information to the function in runtime.
An example of why, how, and where you want this would be helpful, because I fail to grasp the motivation for something like this. Also, I think you should take it to std-proposals@isocpp.org :-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com

El 12/06/2012 18:18, Dave Abrahams escribió:
Passing by reference always defeats copy elision. Why would you want to do that?
Because the in-out reference (I'm talking about non-const references instead of returning by value) might have enough memory/resources to hold the produced value. An example: 1) s has enough capacity, potentially a single allocation std::string s; s.reserve(largest_path); //one allocation std::string ws; ws.reserve(largest_path); //one allocation for( N times ) { calculate_unix_path(s, directory_name, filename[i]...);//no allocation ws = to_wide_string(s); //no allocation print_s(ws); } 2) s's resources not reused, N*2 allocations std::string s; std::string ws; for( N times ) { //allocation, s's previous memory discarded s = calculate_unix_path(directory_name, filename[i]); //w's previously memory discarded ws = to_wide_string(s); print_s(ws); }
You can catch temporaries by rvalue references to reuse external resources. For generic code, catching by value could do some premature pessimization.
Which pessimization is that?
Example: when copy-construction + swap is more expensive than assignment: template<class T> class any_holder { public: any_holder &operator=(any_holder<T> taken_by_value) { using std::swap; swap(t, taken_by_value); return *this; } private: T t; } typedef any_holder< vector<std::string> > any_complex_t; any_complex_t complex, complex2; modify_complex(complex); modify_complex(complex2); //complex2::t's resources //not reused: taken_by_value //was copy-constructed + swapped //with t instead of copy-assigned complex2 = complex; If any_holder implements copy assignment taking a const reference, t's (vector's) resources are reused.
Passing by value has also another downside: it makes your binary interface dependent on the function implementation (do I copy the parameter?). If I change the implementation I need to break ABI.
I don't see how that follows. Leave the ABI alone. Pass-by-value completely insulates the caller from the callee.
If I modify my implementation because I no longer need the internal copy (e.g. the copy was required by an internal function/helper function), I can't optimize the code and change the signature of the function to take a reference, as name mangling changes and I'll need to recompile the caller. If I offer both lvalue and rvalue reference variants I type a bit more but I can safely change the implementation. This might sound a bit silly, but I don't like the idea of defining an interface because I know what I'll do in the implementation details.
I'm really worried about "pass by value is free" and "return by value is free" statements I'm hearing in some C++11 panels.
Where are you hearing that? I've heard Scott Meyers complain about that too, but as far as I can tell, it's a misunderstanding of what's being said.
Apart from some non-really expert C++11 talks I'm attending I remember this issue in the C&B 2011 Panel with Meyers, Alexadrescu and Sutter, (around minute 41). http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2011-C11-Panel-Scott-...
An example of why, how, and where you want this would be helpful, because I fail to grasp the motivation for something like this. Also, I think you should take it to std-proposals@isocpp.org :-)
Yes, sorry, I think it was a bit off topic. One reason is to have multiple return values without packing them on the callee and unpacking them in the caller. Another reason is to have a single implementation that can reuse resources of possibly constructed N out arguments without the need of a lot of overloads. void produce_abcd ( A &a default{1}, B &b default(2) , C &c default(3), D &d default(4)) { //a, b, c, d might be references //to external objects or references to values //constructed with the "default" construction. // //write code as if a, b, c, d were references //to already existing external objects. //... //If a was externally constructed, resources //are reused. a = ... } //Build four new objects [A a, Bb, C c, D c] -> produce_abcd(a, b, c, d), //build new objects and reuse a&b resources [C c2, D c2] -> produce_abcd(a, b, c2, d2), //build new objects reusing a, b, c, d produce_abcd(a, b, c, d), I'm not sure if benefits outweigh the added complexity and such a proposal would have some difficult areas, specially because I'm don't think there is a way to make current pointer to [member]function implementations compatible with that calling convention (the caller must pass the "state" of the arguments in runtime, as a hidden parameter), or without pessimizing pointer to [member]functions. I don't think I could write such a proposal without help from compiler experts. Regards, Ion

El 13/06/2012 1:08, Ion Gaztañaga escribió:
1) s has enough capacity, potentially a single allocation
std::string s; s.reserve(largest_path); //one allocation std::string ws; ws.reserve(largest_path); //one allocation
for( N times ) { calculate_unix_path(s, directory_name, filename[i]...);//no allocation ws = to_wide_string(s); //no allocation print_s(ws); }
Sorry, I meant: to_wide_string(ws, s); //no allocation

On Jun 9, 2012, at 4:21 PM, Daniel Larimer wrote:
I am trying to define my library API and have been using rvalue references and have observed some patterns that I would like to run by the community.
In c++03 I would pass almost everything by const& unless it was to be modified. This results in extra copies any time a temporary is passed.
In c++11 I would pass anything that I plan on 'storing' or 'consuming' by &&. This results in the most efficient code, but 'breaks' lvalue compatibility and forces me to consider having two (or more) versions of every method. Unfortunately, you get a explosion of permutations of rvalue and const& as the number of arguments increases and it makes getting function pointers much more 'ugly'.
Instead of providing two (or more) overloads, one for lvalues and one for rvalue, I have decided to only provide the rvalue overload and if the user wants to pass an lvalue they wrap with std::ref(), std::cref(), std::move() or my own helper copy() which makes the copy explicit and converts the lvalue to a rvalue. (std::ref() and std::cref() could only work if the arguments are template parameters... in which case the method would probably use std::forward<>() to handle the auto-detection of move vs copy semantics.
template<typename T> T copy( const T& v ) { return v; }
If I am writing a method that does not 'store' or 'consume' the input then I use const&
As rvalue references are quite new, this 'convention' may be unexpected by users. How would you feel about using an API that assumed move semantics unless you explicitly specify copy or reference semantics? Is there any reason that there shouldn't be a boost::copy() in boost/utility for use in this situation?
Are there some down sides to this approach that I am missing? In my experience 90% of functions that take std::string() end up using a temporary and 90% of strings are 'calculated', 'used', and 'forgotten', yet most methods take const& and result in a temporary value.
I should probably clarify, that I would use const& for any types that do not benefit from move semantics (no deep copies). But when you are writing template code, you do not want to make that assumption about the type.
Another practice I am considering is making certain classes 'explicit copy only'.
template<typename T> T copy( const T& t ) { return t; }
class test { public: test(){...}; test( test&& t ){...}
private: template<typename T> friend T copy(const T&t);
test& operator=(const test&); // not implemented test( const test& t ){...}
std::vector<char> large_data; };
int main( int argc, char** argv ) { test x; test y = copy(x); test z = x; // error, test(const test&) is private... return 0; }
I would use this for any class that contains any 'movable members', such a strings, vectors, maps, etc. Technically there is no reason why I couldn't copy them, but why shouldn't I attempt move semantics everywhere possible unless I really do want to copy? With implicit copies there is no way for the compiler to warn me that I am doing something potentially expensive.
If it didn't break backward compatibility I would suggest that all of the standard containers adopt an explicit copy or move syntax or at least have a compiler flag to 'enable/disable' implicit copying for 'testing purposes'. Perhaps we could put them in a different namespace for those of us that want to disable implicit copying of deep data types, ie: xc::vector<>, xc::string, etc.
Are these sane conventions? What could go wrong? I am I abusing rvalue references?
Generic code that expects traditional copy syntax is going to fail to compile when used with your convention: template<class T> T min(initializer_list<T> t); template <class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); template <class InputIterator, class RandomAccessIterator> RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last, RandomAccessIterator result_first, RandomAccessIterator result_last); template <class ForwardIterator, class OutputIterator> OutputIterator rotate_copy(ForwardIterator first, ForwardIterator middle, ForwardIterator last, OutputIterator result); template <class InputIterator, class OutputIterator, class T> OutputIterator remove_copy(InputIterator first, InputIterator last, OutputIterator result, const T& value); template <class ForwardIterator, class T> void fill(ForwardIterator first, ForwardIterator last, const T& value); template <class OutputIterator, class Size, class T> OutputIterator fill_n(OutputIterator first, Size n, const T& value); etc. On Jun 9, 2012, at 4:49 PM, Giovanni Piero Deretta wrote:
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
"The best solution" has an implicit "always" in it. Telling programmers they don't have to think, design or measure is a disservice to our industry. Pass-by-value is a good tool to have in the toolbox. It is not always the best solution. There is no solution that is always best. #include <string> #include <vector> #include <chrono> #include <iostream> class A { std::string str_; public: #if 1 explicit A(std::string str) : str_(std::move(str)) {} #else explicit A(const std::string& str) : str_(str) {} explicit A(std::string&& str) : str_(std::move(str)) {} #endif }; static_assert(std::is_nothrow_move_constructible<A>::value, ""); int main() { typedef std::chrono::high_resolution_clock Clock; typedef std::chrono::duration<double, std::milli> ms; std::vector<A> v; const unsigned N = 1000000; v.reserve(N); std::string s("1234567890"); auto t0 = Clock::now(); for (unsigned i = 0; i < N; ++i) v.push_back(A(s)); auto t1 = Clock::now(); std::cout << ms(t1-t0).count() << "ms\n"; } For me this runs about 19% slower one way than the other. And I have no idea how portable that result is. Maybe for your application the 19% speed hit (more or less) is inconsequential. Maybe for someone else's application a 19% speed hit (more or less) is critical. <shrug> We the advise givers have no idea. Pass-by-value is a good tool in the toolbox. It is not free. There are other good tools in the toolbox too. None of them are free either. Howard

On Jun 9, 2012, at 6:03 PM, Howard Hinnant wrote:
On Jun 9, 2012, at 4:21 PM, Daniel Larimer wrote:
Generic code that expects traditional copy syntax is going to fail to compile when used with your convention:
template<class T> T min(initializer_list<T> t);
...
etc.
I suspect that you could create something to wrap the explicit-copy type if you really need to use it in such a case: template<typename T> class implicit_copyable { public: implicit_copyable( T e ) :val(std::move(e)){} implicit_copyable( implicit_copyable&& c ) :val(std::move(c.val)){} implicit_copyable( const implicit_copyable& c ) :val( copy(c.val) ){} operator T&(){ return val; } operator const T&()const { return val; } private: T val; } I suspect that generic algorithms that depend on copy syntax, would not be a good match or even be applicable for types that are implemented as 'explicit copyable only'. In my particular case I am passing 'messages' around and they only ever exist in one place at a time. I want the compiler to tell me when I try to make a copy. The effect is the same as using unique_ptr<Message> except that Message has value semantics and there is no 'extra' heap allocation for Message which is essentially a pointer to the real data. In theory I could 'copy' the message, but that would have to be a carefully considered decision.
On Jun 9, 2012, at 4:49 PM, Giovanni Piero Deretta wrote:
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
"The best solution" has an implicit "always" in it. Telling programmers they don't have to think, design or measure is a disservice to our industry. Pass-by-value is a good tool to have in the toolbox. It is not always the best solution. There is no solution that is always best.
....
For me this runs about 19% slower one way than the other. And I have no idea how portable that result is. Maybe for your application the 19% speed hit (more or less) is inconsequential. Maybe for someone else's application a 19% speed hit (more or less) is critical. <shrug> We the advise givers have no idea.
Pass-by-value is a good tool in the toolbox. It is not free. There are other good tools in the toolbox too. None of them are free either.
Good catch. Rule #1, always profile. I suspect that some guidelines on where to use pass-by-value vs my explicit-copy approach would be helpful. Obviously there is no 'always', but I hate having to think about it every time, so perhaps some rules of thumb are in order.
Howard
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Jun 9, 2012, at 6:44 PM, Daniel Larimer wrote:
In my particular case I am passing 'messages' around and they only ever exist in one place at a time. I want the compiler to tell me when I try to make a copy. The effect is the same as using unique_ptr<Message> except that Message has value semantics and there is no 'extra' heap allocation for Message which is essentially a pointer to the real data.
Perhaps in your particular case a move-only message, or a message with an explicit copy member is a good idea. You might be willing to sacrifice usability with generic-copy-algorithms for this class to get the benefit of being assured that copies either can't happen or are suitably rare. But I wouldn't recommend an explicit copy for more general purpose types, because a general purpose type has to be usable in such a wide variety use cases. Obviously though we do have general purpose move-only types. Howard

On Jun 9, 2012, at 6:58 PM, Howard Hinnant wrote:
On Jun 9, 2012, at 6:44 PM, Daniel Larimer wrote:
In my particular case I am passing 'messages' around and they only ever exist in one place at a time. I want the compiler to tell me when I try to make a copy. The effect is the same as using unique_ptr<Message> except that Message has value semantics and there is no 'extra' heap allocation for Message which is essentially a pointer to the real data.
Perhaps in your particular case a move-only message, or a message with an explicit copy member is a good idea. You might be willing to sacrifice usability with generic-copy-algorithms for this class to get the benefit of being assured that copies either can't happen or are suitably rare.
But I wouldn't recommend an explicit copy for more general purpose types, because a general purpose type has to be usable in such a wide variety use cases. Obviously though we do have general purpose move-only types.
More thought: A type with an explicit copy member is effectively a move-only type as far as general purpose / generic clients are concerned. And C++11 has pretty good support for move only types (you can return them from factory functions, and use them in sequence-permuting generic algorithms such as sort and reverse). So as long as your clients that need a copy are a niche clientele that is a small enough group to be able to know how to copy your class, maybe this isn't so restrictive. Truly general purpose / generic clients can get a lot done with a move-only type. Howard

On Sat, Jun 9, 2012 at 11:03 PM, Howard Hinnant <howard.hinnant@gmail.com> wrote:
As per http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ , if the function is likely to consume or copy the parameter, the best solution is to pass by value. This means you'll only need to provide a single overload.
"The best solution" has an implicit "always" in it. Telling programmers they don't have to think, design or measure is a disservice to our industry. Pass-by-value is a good tool to have in the toolbox. It is not always the best solution. There is no solution that is always best.
Of course it isn't, as it wasn't the existing rule "pass objects of class type by const reference", but is a safe default. [snip test]
For me this runs about 19% slower one way than the other. And I have no idea how portable that result is. Maybe for your application the 19% speed hit (more or less) is inconsequential. Maybe for someone else's application a 19% speed hit (more or less) is critical. <shrug> We the advise givers have no idea.
I didn't actually believe this, so I tested it (gcc 4.6) and you are right. I couldn't measure the actual overhead because the variance on my tests was very high, but the overhead was definitely there. It is surprising, because even with the rvalue copy there is an explicit temporary there.
Pass-by-value is a good tool in the toolbox. It is not free. There are other good tools in the toolbox too. None of them are free either.
Agree. -- gpd

On 09/06/2012 22:21, Daniel Larimer wrote:
In c++11 I would pass anything that I plan on 'storing' or 'consuming' by&&. This results in the most efficient code, but 'breaks' lvalue compatibility and forces me to consider having two (or more) versions of every method. Unfortunately, you get a explosion of permutations of rvalue and const& as the number of arguments increases and it makes getting function pointers much more 'ugly'.
Instead of providing two (or more) overloads, one for lvalues and one for rvalue, I have decided to only provide the rvalue overload and if the user wants to pass an lvalue they wrap with std::ref(), std::cref(), std::move() or my own helper copy() which makes the copy explicit and converts the lvalue to a rvalue. (std::ref() and std::cref() could only work if the arguments are template parameters... in which case the method would probably use std::forward<>() to handle the auto-detection of move vs copy semantics.
This is a terrible design. First, if you have many functions that plan on 'storing' or 'consuming' their arguments, you're clearly doing something wrong. Second, you should use templates which enable perfect forwarding. This way you don't have a combinatorial explosion of the number of overloads, just the one.
participants (13)
-
bibil
-
Daniel Larimer
-
Dave Abrahams
-
Giovanni Piero Deretta
-
Gpderetta
-
Howard Hinnant
-
Ion Gaztañaga
-
Mathias Gaunard
-
Nevin Liber
-
Olaf van der Spek
-
Peter Dimov
-
Sebastian Redl
-
Simonson, Lucanus J