2015-05-11 29 views
2

考虑下面的代码:的boost ::范围::详细:: any_iterator不升压发挥好:: 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 \ N2 b .. 。“)编译时没有进行优化,但是在编译时使用-O2(clang-3.6.0和gcc-4.9.2,boost 1.56.0)编译时会出现段错误或产生垃圾,我不知道哪里出了问题。

此外,当IntCharIterator包装被删除时,代码按照预期的方式工作在任一优化级别。

有人知道这里发生了什么吗?

回答

3

这是Boost.Range中的一个错误:#10493 Since 1.56, any_range with non-reference references can cause UB(警告:目前错误跟踪器具有无效的SSL证书)。这是由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;