17

Is there a way to make boost::combine work with structured bindings and range-based for (so that identifiers in the structure binding actually point to containers' elements instead of nested tuples of whatever boost::combine uses under the hood)? The following (live example) fails to compile:

#include <boost/range/combine.hpp>
#include <iostream>

int main()
{
    std::vector<int> a{1,2,3};
    std::vector<int> b{2,3,4};

    for (auto [f, s] : boost::combine(a, b))
    {
        std::cout << f << ' ' << s << std::endl   
    }
}
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Dev Null
  • 4,731
  • 1
  • 30
  • 46

2 Answers2

7

The real answer is to use either boost::tie or grab the range-v3 zip() which actually yields a std::tuple.


The for educational purposes only answer is just to adapt the structured bindings machinery for boost::tuples::cons. That type already has a get() which works with ADL and does the right thing, so all we need to do is provide tuple_size and tuple_element (which ends up being really easy to do since these exact traits already exist in Boost):

namespace std {
    template <typename T, typename U>
    struct tuple_size<boost::tuples::cons<T, U>>
        : boost::tuples::length<boost::tuples::cons<T, U>>
    { };

    template <size_t I, typename T, typename U>
    struct tuple_element<I, boost::tuples::cons<T, U>>
        : boost::tuples::element<I, boost::tuples::cons<T, U>>
    { };
}

But don't actually do that in real code, since really only the type author should opt-in to this kind of thing.

That'll make the structured binding just work.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • yep, thanks a lot, this is exactly what I was looking for! – Dev Null Apr 10 '19 at 00:46
  • Strange, why this is not a part of the standard? – Audrius Meškauskas Jan 16 '20 at 15:04
  • @h22 because `boost` isn't part of `std` – Caleth Jan 16 '20 at 15:50
  • Do you mean, there is no way to add this somehow bypassing the std:: namespace? I was thinking about just take and include this as part of my project. But some FUD remains within me, so I have decided to ask a separate question on that first. Other ways to iterate over multiple vectors I have seen so far add more complexity than remove. – Audrius Meškauskas Jan 16 '20 at 15:52
1

You can use boost::tie to accomplish this.

#include <boost/range/combine.hpp>
#include <iostream>

int main()
{
    std::vector<int> a{1,2,3};
    std::vector<int> b{2,3,4};
    int f, s;
    for (auto var : boost::combine(a, b))        
    {
        boost::tie(f, s) = var;
        std::cout << f << ' ' << s << std::endl;   
    }
}

Demo.

P.W
  • 26,289
  • 6
  • 39
  • 76