Created on 1998-10-07.00:00:00 last changed 171 months ago
[ Copenhagen: It was generally agreed that this was a defect. Strap poll: NAD - 0. Accept proposed resolution - 10. Leave open - 1. ]
[ Kona: The LWG discussed this at some length.It was agreed that this is a mistake in the design, but there was no consensus on whether it was a defect in the Standard. Straw vote: NAD - 5. Accept proposed resolution - 3. Leave open - 6. ]
Proposed resolution:
Howard believes there is a flaw in this resolution. See c++std-lib-9127. We may need to reopen this issue.
In [depr.lib.binders] in the declaration of binder1st after:
typename Operation::result_type
operator()(const typename Operation::second_argument_type& x) const;
insert:
typename Operation::result_type
operator()(typename Operation::second_argument_type& x) const;
In [depr.lib.binders] in the declaration of binder2nd after:
typename Operation::result_type
operator()(const typename Operation::first_argument_type& x) const;
insert:
typename Operation::result_type
operator()(typename Operation::first_argument_type& x) const;
There are no versions of binders that apply to non-const elements of a sequence. This makes examples like for_each() using bind2nd() on page 521 of "The C++ Programming Language (3rd)" non-conforming. Suitable versions of the binders need to be added.
Further discussion from Nico:
What is probably meant here is shown in the following example:
class Elem { public: void print (int i) const { } void modify (int i) { } };
int main() { vector<Elem> coll(2); for_each (coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Elem::print),42)); // OK for_each (coll.begin(), coll.end(), bind2nd(mem_fun_ref(&Elem::modify),42)); // ERROR }
The error results from the fact that bind2nd() passes its first argument (the argument of the sequence) as constant reference. See the following typical implementation:
template <class Operation> class binder2nd : public unary_function<typename Operation::first_argument_type, typename Operation::result_type> { protected: Operation op; typename Operation::second_argument_type value; public: binder2nd(const Operation& o, const typename Operation::second_argument_type& v) : op(o), value(v) {}typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const { return op(x, value); } };
The solution is to overload operator () of bind2nd for non-constant arguments:
template <class Operation> class binder2nd : public unary_function<typename Operation::first_argument_type, typename Operation::result_type> { protected: Operation op; typename Operation::second_argument_type value; public: binder2nd(const Operation& o, const typename Operation::second_argument_type& v) : op(o), value(v) {}typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const { return op(x, value); } typename Operation::result_type operator()(typename Operation::first_argument_type& x) const { return op(x, value); } };
History | |||
---|---|---|---|
Date | User | Action | Args |
2010-10-21 18:28:33 | admin | set | messages: + msg666 |
2010-10-21 18:28:33 | admin | set | messages: + msg665 |
2010-10-21 18:28:33 | admin | set | messages: + msg664 |
1998-10-07 00:00:00 | admin | create |