
Dill, John wrote:
While having pass-by-value may be more convenient and occur more often, the counter-intuitiveness of the semantics will lead to subtle bugs in people's code who misunderstand or forget bind's behavior in this area.
A bold prediction in the face of contradictory evidence.
Can you elaborate?
In general, arguments of the form "feature X causes frequent real and documented problems right now" carry more weight than "I boldly predict that feature X will inevitably cause problems in the future, and you should change it now as I say, or else."
You may have no problems understanding the library, but the first time I tried to bind with a reference, I ran into the same confusion. I am speaking from my own limited experience with the library. I've read the documentation:
[...]
I know this makes it explicit that you need a ref or cref to have bind store a reference to an object, but there is no reasoning behind this design decision in the documentation, or that I can find in the implementation and I've not stumbled across it in the mail archives.
Reasons, in no particular order: - Lifetime. Storing a reference is unsafe; you need to ensure that the function object returned by the bind() expression will not outlive the referenced entity. The current semantics are safe by default. - Consistency with the first argument. The bound function object is copied, and so are the arguments. It is not possible to infer, in general, whether the function object should be copied or not. When you learn about ref(), you can easily apply your knowledge to bind expressions that store a reference to a function object: bind( ref(f), _1, 0 ); - You can tell whether the bind() expression refers to outside entities by local inspection. If you see no ref(), you can reasonably expect a self-contained function object. - It is not possible to detect, in general, whether an argument needs to be passed by reference: struct F { void operator()(int x); void operator()(long & x); };