Why is it not possible to capture modified lambdas with mutable data members?

This question is related to this previous one , where it was noted that init-capture mutablelambdas are incompatible with the Boost and iterator ranges transformfor some rather hidden and deeply nested errors typedefthat may or may not be easily resolved by hacking Boost.Range sources.

The accepted answer suggests storing the lambda in the object std::function. To avoid a potential lack of functions virtual, I wrote two functional objects that could serve as potential jobs. They are MutableLambda1also called MutableLambda2in the code below.

#include <iostream>
#include <iterator>
#include <vector>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>

// this version is conforming to the Standard
// but is not compatible with boost::transformed
struct MutableLambda1
{
    int delta;     
    template<class T> auto operator()(T elem) { return elem * delta++; }
};

// Instead, this version works with boost::transformed
// but is not conforming to the Standard
struct MutableLambda2
{
    mutable int delta;
    template<class T> auto operator()(T elem) const { return elem * delta++; }
};

// simple example of an algorithm that takes a range and laziy transformes that
// using a function object that stores and modifies internal state
template<class R, class F>
auto scale(R r, F f) 
{
    return r | boost::adaptors::transformed(f);
}

int main()
{
    // real capturing mutable lambda, will not work with boost::transformed
    auto lam = [delta = 1](auto elem) mutable { return elem * delta++; };        
    auto rng = std::vector<int>{ 1, 2, 3, 4 };

    //boost::copy(scale(rng, lam), std::ostream_iterator<int>(std::cout, ","));                 /* ERROR */
    //boost::copy(scale(rng, MutableLambda1{1}), std::ostream_iterator<int>(std::cout, ","));   /* ERROR */
    boost::copy(scale(rng, MutableLambda2{1}), std::ostream_iterator<int>(std::cout, ","));     /* OK!   */
}

Live Example, lam MutableLambda1, 1, 4, 9, 16 MutableLambda2.

5.1.2 - [expr.prim.lambda]

5 [...] const (9.3.1) , - -- mutable. [...]

11 init-capture , init-capture . -, mutable. [...]

, MutableLambda2 , lambda mutable init-capture.

  • init-capture mutable lambdas , (.. )?
  • mutable const ?
  • (bonus), Boost transform , operator() const?
+3
2
template<class L>
struct force_const_call_t {
  mutable L f;
  template<class...Args>
  auto operator()(Args&&...args) const
  { return f(std::forward<Args>(args)...); }
};
template<class L>
force_const_call_t<L> force_const_call(L&&f){
  return {std::forward<L>(f)};
}

, force_const_call(... ) boost mutable (, lambdas mutable callables).

+2

, , .

, Boost.Iterator, Boost.Range boost::adaptors::transformed. Boost.Iterator transform_iterator, , ( )

UnaryFunction Assignable, Copy Constructible f(*i) , f const UnaryFunction, i Iterator f(*i) result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type.

, lambdas, const operator() mutable , . Q & A.

: .

+1

All Articles