Re: reference binding

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? 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: // Start of docs The arguments that bind takes are copied and held internally by the returned function object. For example, in the following code: int i = 5; bind(f, i, _1); a copy of the value of i is stored into the function object. boost::ref and boost::cref can be used to make the function object store a reference to an object, rather than a copy: int i = 5; bind(f, ref(i), _1); // End of docs 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. Best, John

"Dill, John" <john-dill@uiowa.edu> writes:
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?
I can't recall ever having seen a complaint from a user who had a "subtle bug" because something was copied rather than taken by reference, especially in the bind library. The opposite, however, is not true ;-)
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:
// Start of docs The arguments that bind takes are copied and held internally by the returned function object. For example, in the following code:
int i = 5;
bind(f, i, _1);
a copy of the value of i is stored into the function object. boost::ref and boost::cref can be used to make the function object store a reference to an object, rather than a copy:
int i = 5;
bind(f, ref(i), _1); // End of docs
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.
So in summary, you weren't confused about how the library works; you just were unhappy that you had no justification for how it works. That lends no credence to your claim that "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." P.S. if you want to understand the justification, see http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Apr 15, 2004, at 11:08 AM, 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? 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:
// Start of docs The arguments that bind takes are copied and held internally by the returned function object. For example, in the following code:
int i = 5;
bind(f, i, _1);
a copy of the value of i is stored into the function object. boost::ref and boost::cref can be used to make the function object store a reference to an object, rather than a copy:
int i = 5;
bind(f, ref(i), _1); // End of docs
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.
Hello John, There's a big technical reason: If bind would have reference semantics, you could not do this: bind(f, 1, _1) Bind would have to take its arguments as template <class F, class A, class B, ...> bind( F, A&, B&, ...) 1 is a non-const rvalue, which cannot be bound to non-const reference. Cheers, Jaakko

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); };
participants (4)
-
David Abrahams
-
Dill, John
-
Jaakko Jarvi
-
Peter Dimov