#include <iostream>
#include <tuple>
template <std::size_t ... Is>
struct accum_mul;
template <>
struct accum_mul<> : std::integral_constant<std::size_t, 1u>{};
template <std::size_t I, std::size_t ... Is>
struct accum_mul<I, Is...> :
std::integral_constant<std::size_t, I * accum_mul<Is...>::value>{};
template <typename Seq, typename Res = std::tuple<>>
struct coeff;
template <typename Res>
struct coeff<std::index_sequence<>, Res> {
using type = Res;
};
template <std::size_t I, std::size_t ... Is, typename ... TRes>
struct coeff<std::index_sequence<I, Is...>,
std::tuple<TRes...>>
: coeff<std::index_sequence<Is...>,
std::tuple<TRes..., accum_mul<Is...>>> {};
template <std::size_t I, typename coeffs, typename dims, typename Seq>
struct to_multi_index;
template <std::size_t I, typename coeffs, typename dims, std::size_t... Is>
struct to_multi_index<I, coeffs, dims, std::index_sequence<Is...>>
{
using type = std::index_sequence<(I / (std::tuple_element<Is, coeffs>::type::value)
% (std::tuple_element<Is, dims>::type::value))...>;
};
template <typename Indexes, typename coeffs, typename dims, typename dim_indexes>
struct to_multi_indexes;
template <std::size_t... Is, typename coeffs, typename dims, typename dim_indexes>
struct to_multi_indexes<std::index_sequence<Is...>, coeffs, dims, dim_indexes>
{
using type = std::tuple<typename to_multi_index<Is, coeffs, dims, dim_indexes>::type...>;
};
template <std::size_t...Is>
struct all_indexes
{
private:
using as_seq = std::index_sequence<Is...>;
using as_tuple = std::tuple<std::integral_constant<std::size_t, Is>...>;
using dim_index = std::make_index_sequence<sizeof...(Is)>;
using coeffs = typename coeff<as_seq>::type;
using elem_count = accum_mul<Is...>;
using index_seq = std::make_index_sequence<elem_count::value>;
public:
using type = typename to_multi_indexes<index_seq, coeffs, as_tuple, dim_index>::type;
};
template <std::size_t ... Is>
void print(std::index_sequence<Is...>)
{
const int dummy[] = {0, (std::cout << Is << " ", 0)...};
(void) dummy;
std::cout << std::endl;
}
template <typename ...Ts>
void print(const std::tuple<Ts...>&)
{
const int dummy[] = {0, (print(Ts{}), 0)...};
(void) dummy;
}
int main()
{
print(all_indexes<2, 4, 3>::type{});
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgLi4uIElzPgpzdHJ1Y3QgYWNjdW1fbXVsOwoKdGVtcGxhdGUgPD4Kc3RydWN0IGFjY3VtX211bDw+IDogc3RkOjppbnRlZ3JhbF9jb25zdGFudDxzdGQ6OnNpemVfdCwgMXU+e307Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgSSwgc3RkOjpzaXplX3QgLi4uIElzPgpzdHJ1Y3QgYWNjdW1fbXVsPEksIElzLi4uPiA6CiAgICBzdGQ6OmludGVncmFsX2NvbnN0YW50PHN0ZDo6c2l6ZV90LCBJICogYWNjdW1fbXVsPElzLi4uPjo6dmFsdWU+e307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgU2VxLCB0eXBlbmFtZSBSZXMgPSBzdGQ6OnR1cGxlPD4+CnN0cnVjdCBjb2VmZjsKCnRlbXBsYXRlIDx0eXBlbmFtZSBSZXM+CnN0cnVjdCBjb2VmZjxzdGQ6OmluZGV4X3NlcXVlbmNlPD4sIFJlcz4gewogIHVzaW5nIHR5cGUgPSBSZXM7Cn07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgSSwgc3RkOjpzaXplX3QgLi4uIElzLCB0eXBlbmFtZSAuLi4gVFJlcz4Kc3RydWN0IGNvZWZmPHN0ZDo6aW5kZXhfc2VxdWVuY2U8SSwgSXMuLi4+LAogICAgICAgICAgICAgc3RkOjp0dXBsZTxUUmVzLi4uPj4KICAgIDogY29lZmY8c3RkOjppbmRleF9zZXF1ZW5jZTxJcy4uLj4sCiAgICAgICAgICAgIHN0ZDo6dHVwbGU8VFJlcy4uLiwgYWNjdW1fbXVsPElzLi4uPj4+IHt9OwoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IEksIHR5cGVuYW1lIGNvZWZmcywgdHlwZW5hbWUgZGltcywgdHlwZW5hbWUgU2VxPgpzdHJ1Y3QgdG9fbXVsdGlfaW5kZXg7Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QgSSwgdHlwZW5hbWUgY29lZmZzLCB0eXBlbmFtZSBkaW1zLCBzdGQ6OnNpemVfdC4uLiBJcz4Kc3RydWN0IHRvX211bHRpX2luZGV4PEksIGNvZWZmcywgZGltcywgc3RkOjppbmRleF9zZXF1ZW5jZTxJcy4uLj4+CnsKICAgIHVzaW5nIHR5cGUgPSBzdGQ6OmluZGV4X3NlcXVlbmNlPChJIC8gKHN0ZDo6dHVwbGVfZWxlbWVudDxJcywgY29lZmZzPjo6dHlwZTo6dmFsdWUpCiAgICAlIChzdGQ6OnR1cGxlX2VsZW1lbnQ8SXMsIGRpbXM+Ojp0eXBlOjp2YWx1ZSkpLi4uPjsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBJbmRleGVzLCB0eXBlbmFtZSBjb2VmZnMsIHR5cGVuYW1lIGRpbXMsIHR5cGVuYW1lIGRpbV9pbmRleGVzPgpzdHJ1Y3QgdG9fbXVsdGlfaW5kZXhlczsKCnRlbXBsYXRlIDxzdGQ6OnNpemVfdC4uLiBJcywgdHlwZW5hbWUgY29lZmZzLCB0eXBlbmFtZSBkaW1zLCB0eXBlbmFtZSBkaW1faW5kZXhlcz4Kc3RydWN0IHRvX211bHRpX2luZGV4ZXM8c3RkOjppbmRleF9zZXF1ZW5jZTxJcy4uLj4sIGNvZWZmcywgZGltcywgZGltX2luZGV4ZXM+CnsKICAgIHVzaW5nIHR5cGUgPSBzdGQ6OnR1cGxlPHR5cGVuYW1lIHRvX211bHRpX2luZGV4PElzLCBjb2VmZnMsIGRpbXMsIGRpbV9pbmRleGVzPjo6dHlwZS4uLj47Cn07Cgp0ZW1wbGF0ZSA8c3RkOjpzaXplX3QuLi5Jcz4Kc3RydWN0IGFsbF9pbmRleGVzCnsKcHJpdmF0ZToKICAgIHVzaW5nIGFzX3NlcSA9IHN0ZDo6aW5kZXhfc2VxdWVuY2U8SXMuLi4+OwogICAgdXNpbmcgYXNfdHVwbGUgPSBzdGQ6OnR1cGxlPHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8c3RkOjpzaXplX3QsIElzPi4uLj47CiAgICB1c2luZyBkaW1faW5kZXggPSBzdGQ6Om1ha2VfaW5kZXhfc2VxdWVuY2U8c2l6ZW9mLi4uKElzKT47CiAgICB1c2luZyBjb2VmZnMgPSB0eXBlbmFtZSBjb2VmZjxhc19zZXE+Ojp0eXBlOwogICAgdXNpbmcgZWxlbV9jb3VudCA9IGFjY3VtX211bDxJcy4uLj47CiAgICB1c2luZyBpbmRleF9zZXEgPSBzdGQ6Om1ha2VfaW5kZXhfc2VxdWVuY2U8ZWxlbV9jb3VudDo6dmFsdWU+OwpwdWJsaWM6CiAgICB1c2luZyB0eXBlID0gdHlwZW5hbWUgdG9fbXVsdGlfaW5kZXhlczxpbmRleF9zZXEsIGNvZWZmcywgYXNfdHVwbGUsIGRpbV9pbmRleD46OnR5cGU7Cn07CgoKdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IC4uLiBJcz4Kdm9pZCBwcmludChzdGQ6OmluZGV4X3NlcXVlbmNlPElzLi4uPikKewogICAgY29uc3QgaW50IGR1bW15W10gPSB7MCwgKHN0ZDo6Y291dCA8PCBJcyA8PCAiICIsIDApLi4ufTsKICAgICh2b2lkKSBkdW1teTsKICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5Ucz4Kdm9pZCBwcmludChjb25zdCBzdGQ6OnR1cGxlPFRzLi4uPiYpCnsKICAgIGNvbnN0IGludCBkdW1teVtdID0gezAsIChwcmludChUc3t9KSwgMCkuLi59OwogICAgKHZvaWQpIGR1bW15Owp9CgppbnQgbWFpbigpCnsKICAgIHByaW50KGFsbF9pbmRleGVzPDIsIDQsIDM+Ojp0eXBle30pOwp9Cg==