提问人:mecitsari 提问时间:3/30/2023 最后编辑:Benjamin Buchmecitsari 更新时间:3/30/2023 访问量:123
如何将升压范围传递给接受any_range的函数
How to pass boost ranges to a function that accepts any_range
问:
我正在尝试编写一个类函数,该函数接受双随机访问范围。我的目的是能够将任何类型的范围传递给函数,该函数可以是 、 或 boost 范围。该代码适用于 和 ,但是当我尝试使用提升范围时,它会发出警告。boost::any_range
std::vector
std::deque
std::vector
std::deque
我试过了这个:
#include <boost/range/irange.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/any_range.hpp>
#include <iostream>
#include <iterator>
#include <vector>
using Range = boost::any_range<const double, boost::random_access_traversal_tag, const double>;
struct Indexer {
Indexer(const double param_) : param(param_) {}
double operator()(const int i) const
{
return static_cast<double>(i) + param;
}
private:
const double param;
};
class Temp {
public:
void workWithAnyRange(const Range& range) {
workWithAnyRangeTemplated(range);
}
private:
template<typename R>
void workWithAnyRangeTemplated(const R& r) {
for (auto i : r) {
std::cout << "i: " << i << std::endl;
}
}
};
int main() {
Temp temp;
temp.workWithAnyRange(std::vector<double>{1,2,3});
temp.workWithAnyRange(std::deque<double>{1,2,3});
temp.workWithAnyRange(boost::irange(0, 10) | boost::adaptors::transformed(Indexer(15.0))); //introduces the warning
return 0;
}
我得到以下输出:
In file included from /opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator.hpp:22:0,
from /opt/compiler-explorer/libs/boost_1_71_0/boost/range/any_range.hpp:17,
from <source>:5:
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp: In member function 'boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::dereference() const [with WrappedIterator = boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<Indexer, double>, boost::range_detail::integer_iterator<int>, boost::use_default, boost::use_default>; Reference = double; Difference = long int; Buffer = boost::any_iterator_buffer<64ul>; boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference = double&]':
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp:510:57: warning: function returns address of local variable [-Wreturn-local-addr]
return dereference_cast<reference>(*m_it);
^
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp:510:51: note: declared here
return dereference_cast<reference>(*m_it);
^
ASM generation compiler returned: 0
In file included from /opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator.hpp:22:0,
from /opt/compiler-explorer/libs/boost_1_71_0/boost/range/any_range.hpp:17,
from <source>:5:
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp: In member function 'boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::dereference() const [with WrappedIterator = boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<Indexer, double>, boost::range_detail::integer_iterator<int>, boost::use_default, boost::use_default>; Reference = double; Difference = long int; Buffer = boost::any_iterator_buffer<64ul>; boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference = double&]':
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp:510:57: warning: function returns address of local variable [-Wreturn-local-addr]
return dereference_cast<reference>(*m_it);
^
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp:510:51: note: declared here
return dereference_cast<reference>(*m_it);
^
Execution build compiler returned: 0
Program returned: 0
i: 1
i: 2
i: 3
i: 1
i: 2
i: 3
i: 15
i: 16
i: 17
i: 18
i: 19
i: 20
i: 21
i: 22
i: 23
i: 24
如您所见,它输出了一些东西,但警告似乎令人担忧。如果我删除我调用函数的行,警告就会消失。谁能帮我解决这个问题?boost::irange
答:
我感觉我搞砸了编译器选项,因为这似乎有效—— 用户1508716 4分钟前
不,这只是因为它包含提升包含目录,而不是隐藏警告。-isystem
-I
该警告指示转换的结果(右值)通过引用返回。相当令人惊讶,因为您要求引用类型为 .事实上,错误消息确认:double const
/opt/compiler-explorer/libs/boost_1_71_0/boost/range/detail/any_iterator_wrapper.hpp: In member function '
boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::dereference()
const [with
WrappedIterator = boost::iterators::transform_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<Indexer, double>, boost::range_detail::integer_iterator<int>, boost::use_default, boost::use_default>;
Reference = double;
Difference = long int;
Buffer = boost::any_iterator_buffer<64ul>;
boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference = double&;
]':
请注意它如何按照您的要求确认这一点(顶级 const 在 C++ 中的函数签名中并不重要)。但是,它认为,使得不安全的实现:Reference = double
boost::range_detail::any_random_access_iterator_wrapper<WrappedIterator, Reference, Difference, Buffer>::reference = double&
dereference
virtual reference dereference() const
{
return dereference_cast<reference>(*m_it);
}
与 Boost 1.81.0 相比没有问题:https://godbolt.org/z/9qfTzn15T
Indeed boost 1.74.0 包含一个修复程序:https://godbolt.org/z/vEe118f6G
事实上,boost 1.73.0 仍然存在问题:https://godbolt.org/z/EM56Pss5q
所涉及的变化似乎是
474efda Merge pull request #94 from mjendruk/fix-any-range-non-reference-references
哪些链接到 https://github.com/boostorg/range/pull/94“修复具有非参考引用的any_range可能导致 UB”
评论
workWithAnyRangeTemplated
评论