This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 109. Missing binders for non-const sequence elements

Section: 99 [depr.lib.binders] Status: CD1 Submitter: Bjarne Stroustrup Opened: 1998-10-07 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [depr.lib.binders].

View all issues with CD1 status.

Discussion:

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);
>       }
>     };

Proposed resolution:

Howard believes there is a flaw in this resolution. See c++std-lib-9127. We may need to reopen this issue.

In 99 [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 99 [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;`

[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.]

[Copenhagen: It was generally agreed that this was a defect. Strap poll: NAD - 0. Accept proposed resolution - 10. Leave open - 1.]