#include <iostream>
template <unsigned N>
class element {
public:
const static unsigned value = N;
};
template <typename ...Elems>
class set{};
template <typename ...Elems>
void print(set<Elems...> t) {
std::cout << "{";
t.print();
std::cout << "}";
}
template <typename Elem, typename ...Elems>
class set<Elem, Elems...> {
public:
static void print()
{
::print(Elem());
std::cout << ", ";
set<Elems...>::print();
}
};
template <typename Elem>
class set<Elem> {
public:
static void print()
{
::print(Elem());
}
};
template <unsigned N, typename ...Elems>
class set<element<N>, Elems...> {
public:
static void print()
{
std::cout << N << ", ";
set<Elems...>::print();
}
};
template <unsigned N>
class set<element<N>> {
public:
static void print()
{
std::cout << N;
}
};
template <>
class set<> {
public:
static void print(){}
};
template <typename T, typename U>
class join;
template <typename ...Elems>
class join<set<>, set<Elems...>> {
public:
typedef set<Elems...> type;
};
template <typename Elem1, typename ...Elems, typename ...Elems2>
class join<set<Elem1, Elems...>, set<Elems2...>> {
public:
typedef typename join<set<Elems...>, set<Elem1, Elems2...>>::type type;
};
template <typename T, typename U>
class all_subsets_worker;
template <typename Rest>
class all_subsets_worker<set<>, Rest>
{
public:
typedef set<Rest> type;
};
template <typename Elem, typename Rest, typename ...Elems>
class all_subsets_worker<set<Elem, Elems...>, Rest>
{
public:
typedef typename join<
typename all_subsets_worker<set<Elems...>, Rest>::type,
typename all_subsets_worker<set<Elems...>, typename join< set<Elem>, Rest>::type >::type
>::type type;
};
template <typename T>
class all_subsets;
template <typename Elem, typename ...Elems>
class all_subsets<set<Elem, Elems...>> {
public:
typedef typename all_subsets_worker<set<Elem, Elems...>, set<>>::type type;
};
int main(int argc, const char * argv[])
{
auto t = all_subsets<set<element<0>, element<1>, element<2>, element<3>>>::type();
print(t);
std::cout << "\n";
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHVuc2lnbmVkIE4+CmNsYXNzIGVsZW1lbnQgewpwdWJsaWM6CiAgICBjb25zdCBzdGF0aWMgdW5zaWduZWQgdmFsdWUgPSBOOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIC4uLkVsZW1zPgpjbGFzcyBzZXR7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5FbGVtcz4Kdm9pZCBwcmludChzZXQ8RWxlbXMuLi4+IHQpIHsKICAgIHN0ZDo6Y291dCA8PCAieyI7CiAgICB0LnByaW50KCk7CiAgICBzdGQ6OmNvdXQgPDwgIn0iOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRWxlbSwgdHlwZW5hbWUgLi4uRWxlbXM+CmNsYXNzIHNldDxFbGVtLCBFbGVtcy4uLj4gewpwdWJsaWM6CiAgICBzdGF0aWMgdm9pZCBwcmludCgpCiAgICB7CiAgICAgICAgOjpwcmludChFbGVtKCkpOwogICAgICAgIHN0ZDo6Y291dCA8PCAiLCAiOwogICAgICAgIHNldDxFbGVtcy4uLj46OnByaW50KCk7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRWxlbT4KY2xhc3Mgc2V0PEVsZW0+IHsKcHVibGljOgogICAgc3RhdGljIHZvaWQgcHJpbnQoKQogICAgewogICAgICAgIDo6cHJpbnQoRWxlbSgpKTsKICAgIH0KfTsKCnRlbXBsYXRlIDx1bnNpZ25lZCBOLCB0eXBlbmFtZSAuLi5FbGVtcz4KY2xhc3Mgc2V0PGVsZW1lbnQ8Tj4sIEVsZW1zLi4uPiB7CnB1YmxpYzoKICAgIHN0YXRpYyB2b2lkIHByaW50KCkKICAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgTiA8PCAiLCAiOwogICAgICAgIHNldDxFbGVtcy4uLj46OnByaW50KCk7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dW5zaWduZWQgTj4KY2xhc3Mgc2V0PGVsZW1lbnQ8Tj4+IHsKcHVibGljOgogICAgc3RhdGljIHZvaWQgcHJpbnQoKQogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCBOOwogICAgfQp9OwoKdGVtcGxhdGUgPD4KY2xhc3Mgc2V0PD4gewpwdWJsaWM6CiAgICBzdGF0aWMgdm9pZCBwcmludCgpe30KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBVPgpjbGFzcyBqb2luOwoKdGVtcGxhdGUgPHR5cGVuYW1lIC4uLkVsZW1zPgpjbGFzcyBqb2luPHNldDw+LCBzZXQ8RWxlbXMuLi4+PiB7CnB1YmxpYzoKICAgIHR5cGVkZWYgc2V0PEVsZW1zLi4uPiB0eXBlOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEVsZW0xLCB0eXBlbmFtZSAuLi5FbGVtcywgdHlwZW5hbWUgLi4uRWxlbXMyPgpjbGFzcyBqb2luPHNldDxFbGVtMSwgRWxlbXMuLi4+LCBzZXQ8RWxlbXMyLi4uPj4gewpwdWJsaWM6CiAgICB0eXBlZGVmIHR5cGVuYW1lIGpvaW48c2V0PEVsZW1zLi4uPiwgc2V0PEVsZW0xLCBFbGVtczIuLi4+Pjo6dHlwZSB0eXBlOwp9OwoKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBVPgpjbGFzcyBhbGxfc3Vic2V0c193b3JrZXI7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgUmVzdD4KY2xhc3MgYWxsX3N1YnNldHNfd29ya2VyPHNldDw+LCBSZXN0Pgp7CnB1YmxpYzoKICAgIHR5cGVkZWYgc2V0PFJlc3Q+IHR5cGU7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRWxlbSwgdHlwZW5hbWUgUmVzdCwgdHlwZW5hbWUgLi4uRWxlbXM+CmNsYXNzIGFsbF9zdWJzZXRzX3dvcmtlcjxzZXQ8RWxlbSwgRWxlbXMuLi4+LCBSZXN0Pgp7CnB1YmxpYzoKICAgIHR5cGVkZWYgdHlwZW5hbWUgam9pbjwKICAgICAgICAgICAgICAgIHR5cGVuYW1lIGFsbF9zdWJzZXRzX3dvcmtlcjxzZXQ8RWxlbXMuLi4+LCBSZXN0Pjo6dHlwZSwKICAgICAgICAgICAgICAgIHR5cGVuYW1lIGFsbF9zdWJzZXRzX3dvcmtlcjxzZXQ8RWxlbXMuLi4+LCB0eXBlbmFtZSBqb2luPCBzZXQ8RWxlbT4sIFJlc3Q+Ojp0eXBlID46OnR5cGUKICAgICAgICAgICAgPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIGFsbF9zdWJzZXRzOwoKdGVtcGxhdGUgPHR5cGVuYW1lIEVsZW0sIHR5cGVuYW1lIC4uLkVsZW1zPgpjbGFzcyBhbGxfc3Vic2V0czxzZXQ8RWxlbSwgRWxlbXMuLi4+PiB7CnB1YmxpYzoKICAgIHR5cGVkZWYgdHlwZW5hbWUgYWxsX3N1YnNldHNfd29ya2VyPHNldDxFbGVtLCBFbGVtcy4uLj4sIHNldDw+Pjo6dHlwZSB0eXBlOwp9OwoKCgppbnQgbWFpbihpbnQgYXJnYywgY29uc3QgY2hhciAqIGFyZ3ZbXSkKewogICAgYXV0byB0ID0gYWxsX3N1YnNldHM8c2V0PGVsZW1lbnQ8MD4sIGVsZW1lbnQ8MT4sIGVsZW1lbnQ8Mj4sIGVsZW1lbnQ8Mz4+Pjo6dHlwZSgpOwoKICAgIHByaW50KHQpOwoKICAgIHN0ZDo6Y291dCA8PCAiXG4iOwogICAgcmV0dXJuIDA7Cn0=
{{3, 2, 1}, {2, 1}, {1}, {3, 1}, {3}, {}, {2}, {3, 2}, {3, 2, 0}, {2, 0}, {0}, {3, 0}, {3, 1, 0}, {1, 0}, {2, 1, 0}, {3, 2, 1, 0}}