我正在尝试在某些旧版代码中使用boost::any_range
(带有随机访问标签),但是发现它不喜欢lambda。编译错误似乎抱怨缺少lambda对象的默认构造函数。这是预期的行为吗?是设计使然吗?我使用的是Boost版本1.66的MSVC C ++ 17。
文档中提到,transformd_range与输入范围具有相同的类别:
问题显然出在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
答案 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; }));