boost::range::detail::any_iterator 不适合 boost::zip_iterator
boost::range::detail::any_iterator doesn't play well with boost::zip_iterator
考虑以下代码:
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range/detail/any_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <iostream>
#include <vector>
typedef boost::range_detail::any_iterator<
boost::tuple<int &, char &>,
boost::random_access_traversal_tag,
boost::tuple<int &, char &> &,
std::ptrdiff_t
> IntCharIterator;
int main()
{
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<char> v2 = {'a', 'b', 'c', 'd', 'e'};
auto it = IntCharIterator(boost::make_zip_iterator(
boost::make_tuple(v1.begin(), v2.begin()))
);
auto end_ = IntCharIterator(boost::make_zip_iterator(
boost::make_tuple(v1.end(), v2.end()))
);
for (; it != end_; ++it)
std::cerr << it->get<0>() << " " << it->get<1>() << "\n";
return 0;
}
它在没有优化的情况下编译时按预期工作(即打印“1 a\n2 b...”),但在使用 -O2(同时使用 clang-3.6.0)编译时会出现段错误或产生垃圾和 gcc-4.9.2,boost 1.56.0),我不知道出了什么问题。
此外,当删除 IntCharIterator 包装器时,代码在任一优化级别下都按预期工作。
有人知道这是怎么回事吗?
这是 Boost.Range 中的错误:#10493 Since 1.56, any_range with non-reference references can cause UB (warning: currently the bug tracker has an invalid SSL certificate). This was a regression introduced by the fix for bug #5816 any_range requires copyable elements。
奇怪的是,解决方法是让您的 Reference
模板类型参数 const
:
typedef boost::range_detail::any_iterator<
boost::tuple<int &, char &>,
boost::random_access_traversal_tag,
boost::tuple<int &, char &> const, // 'const', no '&'
std::ptrdiff_t
> IntCharIterator;
如果您希望代码适用于 1.56 之前的版本,您可以使用条件预处理器:
typedef boost::range_detail::any_iterator<
boost::tuple<int &, char &>,
boost::random_access_traversal_tag,
#if BOOST_VERSION < 105600
boost::tuple<int &, char &>, // no '&'
#else
boost::tuple<int &, char &> const, // 'const', no '&'
#endif
std::ptrdiff_t
> IntCharIterator;
请注意,在任何情况下 Reference
模板类型参数都应该 而不是 具有 &
;根据 zip_iterator
synopsis,reference_type
与 value_type
相同,因为它是一个引用元组:
typedef reference value_type;
考虑以下代码:
#include <boost/iterator/zip_iterator.hpp>
#include <boost/range/detail/any_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <iostream>
#include <vector>
typedef boost::range_detail::any_iterator<
boost::tuple<int &, char &>,
boost::random_access_traversal_tag,
boost::tuple<int &, char &> &,
std::ptrdiff_t
> IntCharIterator;
int main()
{
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<char> v2 = {'a', 'b', 'c', 'd', 'e'};
auto it = IntCharIterator(boost::make_zip_iterator(
boost::make_tuple(v1.begin(), v2.begin()))
);
auto end_ = IntCharIterator(boost::make_zip_iterator(
boost::make_tuple(v1.end(), v2.end()))
);
for (; it != end_; ++it)
std::cerr << it->get<0>() << " " << it->get<1>() << "\n";
return 0;
}
它在没有优化的情况下编译时按预期工作(即打印“1 a\n2 b...”),但在使用 -O2(同时使用 clang-3.6.0)编译时会出现段错误或产生垃圾和 gcc-4.9.2,boost 1.56.0),我不知道出了什么问题。
此外,当删除 IntCharIterator 包装器时,代码在任一优化级别下都按预期工作。
有人知道这是怎么回事吗?
这是 Boost.Range 中的错误:#10493 Since 1.56, any_range with non-reference references can cause UB (warning: currently the bug tracker has an invalid SSL certificate). This was a regression introduced by the fix for bug #5816 any_range requires copyable elements。
奇怪的是,解决方法是让您的 Reference
模板类型参数 const
:
typedef boost::range_detail::any_iterator<
boost::tuple<int &, char &>,
boost::random_access_traversal_tag,
boost::tuple<int &, char &> const, // 'const', no '&'
std::ptrdiff_t
> IntCharIterator;
如果您希望代码适用于 1.56 之前的版本,您可以使用条件预处理器:
typedef boost::range_detail::any_iterator<
boost::tuple<int &, char &>,
boost::random_access_traversal_tag,
#if BOOST_VERSION < 105600
boost::tuple<int &, char &>, // no '&'
#else
boost::tuple<int &, char &> const, // 'const', no '&'
#endif
std::ptrdiff_t
> IntCharIterator;
请注意,在任何情况下 Reference
模板类型参数都应该 而不是 具有 &
;根据 zip_iterator
synopsis,reference_type
与 value_type
相同,因为它是一个引用元组:
typedef reference value_type;