#include <tuple> // make_tuple, tuple
#include <utility> // pair
#include <vector> // vector
#include <iostream>
#include <string>
#include <ios>
namespace detail {
// the lambda is fully bound with one element from each of the ranges
template<class Op>
void insert_tuples(Op op)
{
// evaluating the lambda will insert the currently bound tuple
op();
}
// "peal off" the first range from the remaining tuple of ranges
template<class Op, class InputIterator1, class... InputIterator2>
void insert_tuples(Op op, std::pair<InputIterator1, InputIterator1> head, std::pair<InputIterator2, InputIterator2>... tail)
{
// "peal off" the elements from the first of the remaining ranges
// NOTE: the recursion will effectively generate the multiple nested for-loops
for (auto it = head.first; it != head.second; ++it) {
// bind the first free variable in the lambda, and
// keep one free variable for each of the remaining ranges
detail::insert_tuples(
[=](InputIterator2... elems) mutable { op(it, elems...); },
tail...
);
}
}
} // namespace detail
// convert a tuple of ranges to the range of tuples representing the Cartesian product
template<class OutputIterator, class... InputIterator>
void cartesian_product(OutputIterator result, std::pair<InputIterator, InputIterator>... dimensions)
{
detail::insert_tuples(
[=](InputIterator... elems) mutable { *result++ = std::make_tuple(*elems...); },
dimensions...
);
}
int main()
{
bool b[] = { false, true };
int i[] = { 0, 1 };
std::string s[] = { "Hello", "World" };
std::vector< std::tuple<bool, int, std::string> > cp = {
std::make_tuple(false, 0, "Hello") ,
std::make_tuple(false, 0, "World"),
std::make_tuple(false, 1, "Hello"),
std::make_tuple(false, 1, "World"),
std::make_tuple(true, 0, "Hello"),
std::make_tuple(true, 0, "World"),
std::make_tuple(true, 1, "Hello"),
std::make_tuple(true, 1, "World")
};
std::vector< std::tuple<bool, int, std::string> > result;
cartesian_product(
std::back_inserter(result),
std::make_pair(std::begin(b), std::end(b)),
std::make_pair(std::begin(i), std::end(i)),
std::make_pair(std::begin(s), std::end(s))
);
std::cout << std::boolalpha << (result==cp) << "\n";
// now use a single flat loop over result to do your own thing
for (auto t: result) {
std::cout << std::get<0>(t) << ", ";
std::cout << std::get<1>(t) << ", ";
std::cout << std::get<2>(t) << "\n";
}
}
I2luY2x1ZGUgPHR1cGxlPiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1ha2VfdHVwbGUsIHR1cGxlCiNpbmNsdWRlIDx1dGlsaXR5PiAgICAgICAgICAgICAgICAgICAgICAvLyBwYWlyCiNpbmNsdWRlIDx2ZWN0b3I+ICAgICAgICAgICAgICAgICAgICAgICAvLyB2ZWN0b3IKI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8aW9zPgogCm5hbWVzcGFjZSBkZXRhaWwgewogCi8vIHRoZSBsYW1iZGEgaXMgZnVsbHkgYm91bmQgd2l0aCBvbmUgZWxlbWVudCBmcm9tIGVhY2ggb2YgdGhlIHJhbmdlcwp0ZW1wbGF0ZTxjbGFzcyBPcD4Kdm9pZCBpbnNlcnRfdHVwbGVzKE9wIG9wKQp7CiAgICAgICAgLy8gZXZhbHVhdGluZyB0aGUgbGFtYmRhIHdpbGwgaW5zZXJ0IHRoZSBjdXJyZW50bHkgYm91bmQgdHVwbGUKICAgICAgICBvcCgpOwp9CiAKLy8gInBlYWwgb2ZmIiB0aGUgZmlyc3QgcmFuZ2UgZnJvbSB0aGUgcmVtYWluaW5nIHR1cGxlIG9mIHJhbmdlcwp0ZW1wbGF0ZTxjbGFzcyBPcCwgY2xhc3MgSW5wdXRJdGVyYXRvcjEsIGNsYXNzLi4uIElucHV0SXRlcmF0b3IyPgp2b2lkIGluc2VydF90dXBsZXMoT3Agb3AsIHN0ZDo6cGFpcjxJbnB1dEl0ZXJhdG9yMSwgSW5wdXRJdGVyYXRvcjE+IGhlYWQsIHN0ZDo6cGFpcjxJbnB1dEl0ZXJhdG9yMiwgSW5wdXRJdGVyYXRvcjI+Li4uIHRhaWwpCnsKICAgICAgICAvLyAicGVhbCBvZmYiIHRoZSBlbGVtZW50cyBmcm9tIHRoZSBmaXJzdCBvZiB0aGUgcmVtYWluaW5nIHJhbmdlcwogICAgICAgIC8vIE5PVEU6IHRoZSByZWN1cnNpb24gd2lsbCBlZmZlY3RpdmVseSBnZW5lcmF0ZSB0aGUgbXVsdGlwbGUgbmVzdGVkIGZvci1sb29wcwogICAgICAgIGZvciAoYXV0byBpdCA9IGhlYWQuZmlyc3Q7IGl0ICE9IGhlYWQuc2Vjb25kOyArK2l0KSB7CiAgICAgICAgICAgICAgICAvLyBiaW5kIHRoZSBmaXJzdCBmcmVlIHZhcmlhYmxlIGluIHRoZSBsYW1iZGEsIGFuZAogICAgICAgICAgICAgICAgLy8ga2VlcCBvbmUgZnJlZSB2YXJpYWJsZSBmb3IgZWFjaCBvZiB0aGUgcmVtYWluaW5nIHJhbmdlcwogICAgICAgICAgICAgICAgZGV0YWlsOjppbnNlcnRfdHVwbGVzKAogICAgICAgICAgICAgICAgICAgICAgICBbPV0oSW5wdXRJdGVyYXRvcjIuLi4gZWxlbXMpIG11dGFibGUgeyBvcChpdCwgZWxlbXMuLi4pOyB9LAogICAgICAgICAgICAgICAgICAgICAgICB0YWlsLi4uCiAgICAgICAgICAgICAgICApOwogICAgICAgIH0KfQogCn0gICAgICAgLy8gbmFtZXNwYWNlIGRldGFpbAogCi8vIGNvbnZlcnQgYSB0dXBsZSBvZiByYW5nZXMgdG8gdGhlIHJhbmdlIG9mIHR1cGxlcyByZXByZXNlbnRpbmcgdGhlIENhcnRlc2lhbiBwcm9kdWN0CnRlbXBsYXRlPGNsYXNzIE91dHB1dEl0ZXJhdG9yLCBjbGFzcy4uLiBJbnB1dEl0ZXJhdG9yPgp2b2lkIGNhcnRlc2lhbl9wcm9kdWN0KE91dHB1dEl0ZXJhdG9yIHJlc3VsdCwgc3RkOjpwYWlyPElucHV0SXRlcmF0b3IsIElucHV0SXRlcmF0b3I+Li4uIGRpbWVuc2lvbnMpCnsKICAgICAgICBkZXRhaWw6Omluc2VydF90dXBsZXMoCiAgICAgICAgICAgICAgICAgWz1dKElucHV0SXRlcmF0b3IuLi4gZWxlbXMpIG11dGFibGUgeyAqcmVzdWx0KysgPSBzdGQ6Om1ha2VfdHVwbGUoKmVsZW1zLi4uKTsgfSwKICAgICAgICAgICAgICAgICBkaW1lbnNpb25zLi4uCiAgICAgICAgKTsKfQogCmludCBtYWluKCkgCiB7CiAgICBib29sIGJbXSA9IHsgZmFsc2UsIHRydWUgfTsKICAgIGludCBpW10gPSB7IDAsIDEgfTsKICAgIHN0ZDo6c3RyaW5nIHNbXSA9IHsgIkhlbGxvIiwgIldvcmxkIiB9OwogCiAgICBzdGQ6OnZlY3Rvcjwgc3RkOjp0dXBsZTxib29sLCBpbnQsIHN0ZDo6c3RyaW5nPiA+IGNwID0gewogICAgICAgICAgICBzdGQ6Om1ha2VfdHVwbGUoZmFsc2UsIDAsICJIZWxsbyIpICwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKGZhbHNlLCAwLCAiV29ybGQiKSwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKGZhbHNlLCAxLCAiSGVsbG8iKSwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKGZhbHNlLCAxLCAiV29ybGQiKSwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKHRydWUsICAwLCAiSGVsbG8iKSwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKHRydWUsICAwLCAiV29ybGQiKSwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKHRydWUsICAxLCAiSGVsbG8iKSwKICAgICAgICAgICAgc3RkOjptYWtlX3R1cGxlKHRydWUsICAxLCAiV29ybGQiKQogICAgfTsKIAogICAgc3RkOjp2ZWN0b3I8IHN0ZDo6dHVwbGU8Ym9vbCwgaW50LCBzdGQ6OnN0cmluZz4gPiByZXN1bHQ7CiAgICBjYXJ0ZXNpYW5fcHJvZHVjdCgKICAgICAgICAgICAgc3RkOjpiYWNrX2luc2VydGVyKHJlc3VsdCksCiAgICAgICAgICAgIHN0ZDo6bWFrZV9wYWlyKHN0ZDo6YmVnaW4oYiksIHN0ZDo6ZW5kKGIpKSwKICAgICAgICAgICAgc3RkOjptYWtlX3BhaXIoc3RkOjpiZWdpbihpKSwgc3RkOjplbmQoaSkpLAogICAgICAgICAgICBzdGQ6Om1ha2VfcGFpcihzdGQ6OmJlZ2luKHMpLCBzdGQ6OmVuZChzKSkKICAgICk7CiAKICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmJvb2xhbHBoYSA8PCAocmVzdWx0PT1jcCkgPDwgIlxuIjsKIAogICAgLy8gbm93IHVzZSBhIHNpbmdsZSBmbGF0IGxvb3Agb3ZlciByZXN1bHQgdG8gZG8geW91ciBvd24gdGhpbmcKICAgIGZvciAoYXV0byB0OiByZXN1bHQpIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgc3RkOjpnZXQ8MD4odCkgPDwgIiwgIjsKICAgICAgICBzdGQ6OmNvdXQgPDwgc3RkOjpnZXQ8MT4odCkgPDwgIiwgIjsKICAgICAgICBzdGQ6OmNvdXQgPDwgc3RkOjpnZXQ8Mj4odCkgPDwgIlxuIjsKICAgIH0KIH0gIA==