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 の両方を使用) でコンパイルすると、セグメンテーション違反が発生するか、ガベージが生成されます。ブースト 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_iteratorreference_typevalue_type

typedef reference value_type;
于 2015-05-11T14:26:30.983 に答える