通过boost :: any_range

时间:2019-04-25 14:50:05

标签: c++11 boost boost-range boost-adaptors

我正在尝试在某些旧版代码中使用boost::any_range(带有随机访问标签),但是发现它不喜欢lambda。编译错误似乎抱怨缺少lambda对象的默认构造函数。这是预期的行为吗?是设计使然吗?我使用的是Boost版本1.66的MSVC C ++ 17。

文档中提到,transformd_range与输入范围具有相同的类别:

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

问题显然出在boost::any_range中的某个地方,因为如果我只是使用auto,它就可以工作(参见下面的rngneg_auto

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

对于前两种情况,程序将打印

Second element is -2
Second element is -2

第三是编译错误(我认为是因为lambda不是默认可构造的):

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

1 个答案:

答案 0 :(得分:0)

令人窒息,因为它试图找出如何从transformed_range构造any_range,并认为lambda是默认的可构造类型。我没有深入研究为什么,但是我想这是因为没有明确表示不是,并且lambda的类型是唯一的。当然,尝试默认构造lambda的类型是没有意义的。

我要说的最简单的方法是使用一种类型(如果通过标准模板)可以清楚地知道它不能默认构造,即std :: function <>。编译:

const double_range rngneg_lambda = v | transformed(static_cast<std::function<double(double)>>([](double x) { return -x; }));