在boost元组、zip_iterator等中使用std::get和std::tie

7

如何在使用boost构造时,同时使用std::get<>()std::tie<>()

例如:我想使用基于范围的for循环迭代多个容器。我可以实现一个zip函数,该函数使用boost::zip_iterator

 #include <boost/iterator/zip_iterator.hpp>
 #include <boost/range.hpp>

 template <typename... TContainer>
 auto zip(TContainer&... containers) -> boost::iterator_range<boost::zip_iterator<decltype(boost::make_tuple(std::begin(containers)...))>> {
    auto zip_begin = boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...));
    auto zip_end = boost::make_zip_iterator(boost::make_tuple(std::end(containers)...));
    return boost::make_iterator_range(zip_begin, zip_end);
 }

现在我可以像这样使用它:
std:list<int> a;
std::vector<double> b;
...
for (auto t : zip(a, b)) {
   // access elements by boost::get<0>(t), boost::get<1>(t)
   // or use boost::tie(a_element, b_element)
}

当我调用一些期望std::tuplestd::pair的其他方法时(需要进行转换),会出现问题,因为代码的其余部分使用std::tuples,或者当泛型代码使用std::get<>()和/或std::tie()时会出现问题。
我发现了一些补丁,为zip_iterator添加了std::tuple支持,但这些补丁没有应用在我的版本中(我使用的是Boost 1.54)。
我是否漏掉了什么?我有哪些选项可以强制zip_iterator返回std::tuple,或使std::getstd::tie等在boost类型中可用?

2
不幸的是,即使在1.55版本中,这些补丁仍未被应用。这是一个链接到工单的链接:https://svn.boost.org/trac/boost/ticket/7526。看起来还没有任何活动,我不确定为什么。 - void-pointer
@void-pointer 一个关于boost::fusion的修复已经在2017年3月提交并合并:https://github.com/boostorg/iterator/pull/2,并且可以在Boost 1.64.0中使用。 - Torbjörn
2个回答

0

在boost >= 1.55中使用boost::combine。

for (auto a_tuple: boost::combine(va, vb)) {...} 或者

BOOST_FOREACH(boost::tie(elem_a, elem_b), boost::combine(va, vb)) {...}


这替换了我的zip函数实现 - 很好知道。但是它与我提到的std::tiestd::tuple有完全相同的问题。它返回zip迭代器的范围,这些迭代器无法解引用为std::tuple。也许我漏掉了什么... - Johny
1
是的,但那不是我的问题 - 我问的是关于STL工具的使用,因为代码的其余部分使用了stl:tuplestd:tie等。 - Johny
是的,我也有同样的问题,但我认为使用boost_foreachboost::tie就足够简洁了。如果无法避免使用std::tuple->std::tie,你可以再次使用std::make_tupleelem_a, elem_b。因此,我认为坚持使用std::tie一个boost::tuple是没有意义的。 - squid

0

你试过了吗?

#include <boost/iterator/zip_iterator.hpp>
#include <boost/range.hpp>
#include <tuple>

template <typename... TContainer> auto zip(TContainer&... containers) ->
boost::iterator_range<boost::zip_iterator<decltype(std::make_tuple(std::begin(containers)...))>> {
                                                   ^^^
    auto zip_begin = boost::make_zip_iterator(std::make_tuple(std::begin(containers)...));
                                              ^^^
    auto zip_end = boost::make_zip_iterator(std::make_tuple(std::end(containers)...));
                                            ^^^
    return boost::make_iterator_range(zip_begin, zip_end);
 }

1
是的,我有。但是似乎Boost缺少一些用于std::tuple的类型特性。这些特性是通过我提到的那些补丁添加的,但是在我的Boost版本中我没有看到它们。也许我需要包含一些其他的头文件(比如Boost.Fusion中的std::tuple适配器)。 - Johny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接