2

考虑以下代码:

#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 包装器被删除时,代码在任一优化级别上都可以按预期工作。

有谁知道这里发生了什么?

4

1 回答 1

3

这是 Boost.Range 中的一个错误:#10493从 1.56 开始,带有非引用引用的 any_range 可能会导致 UB(警告:当前错误跟踪器的 SSL 证书无效)。这是针对错误 #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概要, thereference_type与 相同value_type,因为它是一个引用元组:

typedef reference value_type;
于 2015-05-11T14:26:30.983 回答