Random access of boost::transformed_range via boost::any_range
10:43 25 Apr 2019

I'm trying to use boost::any_range (with random access tag) in some legacy code, but found that it does not like lambdas. Compilation error seems to complain about the lack of default constructor for lambda objects. Is this expected behavior? Is it by design? I'm on MSVC C++17 with boost version 1.66.

Documentation mentions that transformed_range has the same category as input range:

https://www.boost.org/doc/libs/1_66_0/libs/range/doc/html/range/reference/adaptors/reference/transformed.html

The problem is obviously in somewhere in boost::any_range, because if I just use auto, it works (cf rngneg_auto below)

#include 
#include 
#include 
#include 

using boost::adaptors::transformed;

using double_range = boost::any_range;

struct negate
{
    constexpr double operator() (const double x) const
    {
        return -x;
    }
};

int main(int argc, char** argv) 
{
    const std::vector v{ 1.0, 2.0, 3.0 };

    // this works
    const auto rngneg_auto = v | transformed([](double x) { return -x; });
    std::cout << "Second element is " << rngneg_auto[1] << std::endl;

    // ... and this
    const double_range rngneg = v | transformed(negate());
    std::cout << "Second element is " << rngneg[1] << std::endl;

#if 0
    // but not that
    const double_range rngneg_lambda = v | transformed([](double x) { return -x; });
    std::cout << "Second element is " << rngneg_lambda[1] << std::endl;
#endif

    return 0;
}

For the first two cases, the program prints

Second element is -2
Second element is -2

Third is a compilation error (I think it's because lambdas aren't default-constructible):

1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(733): error C2280: 'main:: &main::::operator =(const main:: &)': attempting to reference a deleted function
1> ***: note: see declaration of 'main::::operator ='
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(733): note: while compiling class template member function 'void boost::optional_detail::optional_base::assign_value(main:: &&)'
1>        with
1>        [
1>            T=main::
1>        ]
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(262): note: see reference to function template instantiation 'void boost::optional_detail::optional_base::assign_value(main:: &&)' being compiled
1>        with
1>        [
1>            T=main::
1>        ]
1>\boost.org\boost\1.66.0\include\boost\optional\optional.hpp(831): note: see reference to class template instantiation 'boost::optional_detail::optional_base' being compiled
1>        with
1>        [
1>            T=main::
1>        ]
1>\boost.org\boost\1.66.0\include\boost\range\detail\default_constructible_unary_fn.hpp(48): note: see reference to class template instantiation 'boost::optional' being compiled
1>        with
1>        [
1>            F=main::
1>        ]
1>\boost.org\boost\1.66.0\include\boost\utility\detail\result_of_iterate.hpp(70): note: see reference to class template instantiation 'boost::range_detail::default_constructible_unary_fn_wrapper' being compiled
1>        with
1>        [
1>            F=main::,
1>            R=double
1>        ]
1>\boost.org\boost\1.66.0\include\boost\utility\detail\result_of_iterate.hpp(43): note: see reference to class template instantiation 'boost::detail::cpp0x_result_of' being compiled
1>        with
1>        [
1>            F=const boost::range_detail::default_constructible_unary_fn_wrapper,double> &,
1>            T0=const double &
1>        ]
1>\boost.org\boost\1.66.0\include\boost\mpl\eval_if.hpp(41): note: see reference to class template instantiation 'boost::result_of' being compiled
1>        with
1>        [
1>            UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper,double>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\iterator\iterator_adaptor.hpp(154): note: see reference to class template instantiation 'boost::mpl::eval_if,DefaultNullaryFn,boost::mpl::identity>' being compiled
1>        with
1>        [
1>            T=boost::iterators::use_default,
1>            DefaultNullaryFn=boost::result_of,double> &(const double &)>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\iterator\transform_iterator.hpp(55): note: see reference to class template instantiation 'boost::iterators::detail::ia_dflt_help>' being compiled
1>        with
1>        [
1>            Reference=boost::iterators::use_default,
1>            UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper,double>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\iterator\transform_iterator.hpp(81): note: see reference to class template instantiation 'boost::iterators::detail::transform_iterator_base' being compiled
1>        with
1>        [
1>            UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper,double>,
1>            Iterator=std::_Vector_const_iterator>>,
1>            Reference=boost::iterators::use_default,
1>            Value=boost::iterators::use_default
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.14.26428\include\xutility(652): note: see reference to class template instantiation 'boost::iterators::transform_iterator,It,boost::iterators::use_default,boost::iterators::use_default>' being compiled
1>        with
1>        [
1>            F=main::,
1>            R=double,
1>            It=std::_Vector_const_iterator>>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\iterator\iterator_categories.hpp(120): note: see reference to class template instantiation 'std::iterator_traits' being compiled
1>        with
1>        [
1>            Iterator=boost::iterators::transform_iterator,double>,std::_Vector_const_iterator>>,boost::iterators::use_default,boost::iterators::use_default>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\range\iterator_range_core.hpp(156): note: see reference to class template instantiation 'boost::iterators::iterator_traversal' being compiled
1>        with
1>        [
1>            IteratorT=boost::iterators::transform_iterator,double>,std::_Vector_const_iterator>>,boost::iterators::use_default,boost::iterators::use_default>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\range\iterator_range_core.hpp(436): note: see reference to class template instantiation 'boost::iterator_range_detail::pure_iterator_traversal' being compiled
1>        with
1>        [
1>            IteratorT=boost::iterators::transform_iterator,double>,std::_Vector_const_iterator>>,boost::iterators::use_default,boost::iterators::use_default>
1>        ]
1>\boost.org\boost\1.66.0\include\boost\range\adaptor\transformed.hpp(44): note: see reference to class template instantiation 'boost::iterator_range,It,boost::iterators::use_default,boost::iterators::use_default>>' being compiled
1>        with
1>        [
1>            F=main::,
1>            R=double,
1>            It=std::_Vector_const_iterator>>
1>        ]
1>***: note: see reference to class template instantiation 'boost::range_detail::transformed_range,const std::vector>>' being compiled
1>        with
1>        [
1>            _Ty=double
1>        ]
1>***: note: 'main:: &main::::operator =(const main:: &)': function was explicitly deleted
c++11 boost boost-range boost-adaptors