
    #include <cstddef>
    #include <utility>
    #include <vector>
    #include <tuple>
    #include <string>
    #include <iostream>
     
    using std::size_t;
     
    template<size_t...> struct seq {};
    template<size_t Min, size_t Max, size_t... s>
    struct make_seq:make_seq< Min, Max-1, Max-1, s... > {};
    template<size_t Min, size_t... s>
    struct make_seq< Min, Min, s... > {
        typedef seq<s...> type;
    };
    template<size_t Max, size_t Min=0>
    using MakeSeq = typename make_seq<Min, Max>::type;
     
    size_t product_size() {
      return 1;
    }
    template<typename... Sizes>
    size_t product_size( size_t x, Sizes... tail ) {
      return x * product_size(tail...);
    }
    namespace details {
      template<typename max_iterator, typename Lambda>
      void for_each_index( max_iterator mbegin, max_iterator mend, Lambda&& f, std::vector<size_t>& idx ) {
        if (mbegin == mend) {
          f(idx);
        } else {
          for (size_t i = 0; i < *mbegin; ++i) {
            idx.push_back(i);
            for_each_index(mbegin+1, mend, f, idx);
            idx.pop_back();
          }
        }
      }
      template<typename Lambda>
      void for_each_index( std::vector<size_t> const& maxes, Lambda&& f ) {
        std::vector<size_t> idx;
        details::for_each_index( maxes.begin(), maxes.end(), f, idx );
      }
      template<size_t... s, typename... Ts>
      std::vector< std::tuple<Ts...> > does_it_blend( seq<s...>, std::tuple< std::vector<Ts>... >const& input ) {
        std::vector< std::tuple<Ts...> > retval;
        retval.reserve( product_size( std::get<s>(input).size()... ) );
        std::vector<size_t> maxes = {
          (std::get<s>(input).size())...
        };
        for_each_index( maxes, [&](std::vector<size_t> const& idx){
          retval.emplace_back( std::get<s>(input)[idx[s]]... );
        });
        return retval;
      }
    }
    template<typename... Ts>
    std::vector< std::tuple<Ts...> > does_it_blend( std::tuple< std::vector<Ts>... >const& input ) {
      return details::does_it_blend( MakeSeq< sizeof...(Ts) >(), input );
    }
     
    int main() {
      std::tuple< std::vector<int>, std::vector<bool>, std::vector<std::string> > input {
        { 1, 2, 3}, { false, true}, { "Hello", "World"}
      };
     
      // should become 3 x 2 x 2 = 12 cases { {1, false, "Hello"}, ... , {3, true, "World"} } 
      std::vector< std::tuple<int, bool, std::string> > test_cases = does_it_blend( input );
      
      for( auto&& x:test_cases ) {
        std::cout << std::get<0>(x) << "," << std::get<1>(x) << "," << std::get<2>(x) << "\n";
      }
    }

