jeudi 25 avril 2019

Random access of boost::transformed_range via boost::any_range

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 <boost/range/adaptor/transformed.hpp>
#include <boost/range/any_range.hpp>
#include <iostream>
#include <vector>

using boost::adaptors::transformed;

using double_range = boost::any_range<const double
                                      , boost::random_access_traversal_tag
                                      , const double>;

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

int main(int argc, char** argv) 
{
    const std::vector<double> 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::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>::operator =(const main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &)': attempting to reference a deleted function
1> ***: note: see declaration of 'main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>::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<T>::assign_value(main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &&)'
1>        with
1>        [
1>            T=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
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<T>::assign_value(main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &&)' being compiled
1>        with
1>        [
1>            T=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
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<T>' being compiled
1>        with
1>        [
1>            T=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
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<F>' being compiled
1>        with
1>        [
1>            F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>
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<F,R>' being compiled
1>        with
1>        [
1>            F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,
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<F (T0)>' being compiled
1>        with
1>        [
1>            F=const boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,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<const UnaryFunc &(const double &)>' being compiled
1>        with
1>        [
1>            UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,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<boost::is_same<T,boost::iterators::use_default>,DefaultNullaryFn,boost::mpl::identity<T>>' being compiled
1>        with
1>        [
1>            T=boost::iterators::use_default,
1>            DefaultNullaryFn=boost::result_of<const boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,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<Reference,boost::result_of<const UnaryFunc &(const double &)>>' being compiled
1>        with
1>        [
1>            Reference=boost::iterators::use_default,
1>            UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,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<UnaryFunc,Iterator,Reference,Value>' being compiled
1>        with
1>        [
1>            UnaryFunc=boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,
1>            Iterator=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,
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<boost::range_detail::default_constructible_unary_fn_wrapper<F,R>,It,boost::iterators::use_default,boost::iterators::use_default>' being compiled
1>        with
1>        [
1>            F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,
1>            R=double,
1>            It=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>
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<Iterator>' being compiled
1>        with
1>        [
1>            Iterator=boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,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<IteratorT>' being compiled
1>        with
1>        [
1>            IteratorT=boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,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<IteratorT>' being compiled
1>        with
1>        [
1>            IteratorT=boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,double>,std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>,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<boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<F,R>,It,boost::iterators::use_default,boost::iterators::use_default>>' being compiled
1>        with
1>        [
1>            F=main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,
1>            R=double,
1>            It=std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<double>>>
1>        ]
1>***: note: see reference to class template instantiation 'boost::range_detail::transformed_range<main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>,const std::vector<double,std::allocator<_Ty>>>' being compiled
1>        with
1>        [
1>            _Ty=double
1>        ]
1>***: note: 'main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65>::operator =(const main::<lambda_6f21fa0f6ab2ea01b2b99a85be3eab65> &)': function was explicitly deleted

Aucun commentaire:

Enregistrer un commentaire