#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 <unsigned N>
void print(element<N> t)
{
std::cout << N;
}
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 <>
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 ...Elems>
class all_subsets<set<Elems...>> {
public:
typedef typename all_subsets_worker<set<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();
auto p = all_subsets<set<>>::type();
print(t);
std::cout << "\n";
print(p);
std::cout << "\n";
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHVuc2lnbmVkIE4+CmNsYXNzIGVsZW1lbnQgewpwdWJsaWM6CiAgICBjb25zdCBzdGF0aWMgdW5zaWduZWQgdmFsdWUgPSBOOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIC4uLkVsZW1zPgpjbGFzcyBzZXR7fTsKCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5FbGVtcz4Kdm9pZCBwcmludChzZXQ8RWxlbXMuLi4+IHQpIHsKICAgIHN0ZDo6Y291dCA8PCAieyI7CiAgICB0LnByaW50KCk7CiAgICBzdGQ6OmNvdXQgPDwgIn0iOwp9Cgp0ZW1wbGF0ZSA8dW5zaWduZWQgTj4Kdm9pZCBwcmludChlbGVtZW50PE4+IHQpCnsKICAgIHN0ZDo6Y291dCA8PCBOOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRWxlbSwgdHlwZW5hbWUgLi4uRWxlbXM+CmNsYXNzIHNldDxFbGVtLCBFbGVtcy4uLj4gewpwdWJsaWM6CiAgICBzdGF0aWMgdm9pZCBwcmludCgpCiAgICB7CiAgICAgICAgOjpwcmludChFbGVtKCkpOwogICAgICAgIHN0ZDo6Y291dCA8PCAiLCAiOwogICAgICAgIHNldDxFbGVtcy4uLj46OnByaW50KCk7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRWxlbT4KY2xhc3Mgc2V0PEVsZW0+IHsKcHVibGljOgogICAgc3RhdGljIHZvaWQgcHJpbnQoKQogICAgewogICAgICAgIDo6cHJpbnQoRWxlbSgpKTsKICAgIH0KfTsKCnRlbXBsYXRlIDw+CmNsYXNzIHNldDw+IHsKcHVibGljOgogICAgc3RhdGljIHZvaWQgcHJpbnQoKXt9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVT4KY2xhc3Mgam9pbjsKCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5FbGVtcz4KY2xhc3Mgam9pbjxzZXQ8Piwgc2V0PEVsZW1zLi4uPj4gewpwdWJsaWM6CiAgICB0eXBlZGVmIHNldDxFbGVtcy4uLj4gdHlwZTsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBFbGVtMSwgdHlwZW5hbWUgLi4uRWxlbXMsIHR5cGVuYW1lIC4uLkVsZW1zMj4KY2xhc3Mgam9pbjxzZXQ8RWxlbTEsIEVsZW1zLi4uPiwgc2V0PEVsZW1zMi4uLj4+IHsKcHVibGljOgogICAgdHlwZWRlZiB0eXBlbmFtZSBqb2luPHNldDxFbGVtcy4uLj4sIHNldDxFbGVtMSwgRWxlbXMyLi4uPj46OnR5cGUgdHlwZTsKfTsKCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVT4KY2xhc3MgYWxsX3N1YnNldHNfd29ya2VyOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFJlc3Q+CmNsYXNzIGFsbF9zdWJzZXRzX3dvcmtlcjxzZXQ8PiwgUmVzdD4KewpwdWJsaWM6CiAgICB0eXBlZGVmIHNldDxSZXN0PiB0eXBlOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEVsZW0sIHR5cGVuYW1lIFJlc3QsIHR5cGVuYW1lIC4uLkVsZW1zPgpjbGFzcyBhbGxfc3Vic2V0c193b3JrZXI8c2V0PEVsZW0sIEVsZW1zLi4uPiwgUmVzdD4KewpwdWJsaWM6CiAgICB0eXBlZGVmIHR5cGVuYW1lIGpvaW48CiAgICAgICAgICAgICAgICB0eXBlbmFtZSBhbGxfc3Vic2V0c193b3JrZXI8c2V0PEVsZW1zLi4uPiwgUmVzdD46OnR5cGUsCiAgICAgICAgICAgICAgICB0eXBlbmFtZSBhbGxfc3Vic2V0c193b3JrZXI8c2V0PEVsZW1zLi4uPiwgdHlwZW5hbWUgam9pbjwgc2V0PEVsZW0+LCBSZXN0Pjo6dHlwZSA+Ojp0eXBlCiAgICAgICAgICAgID46OnR5cGUgdHlwZTsKfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpjbGFzcyBhbGxfc3Vic2V0czsKCnRlbXBsYXRlIDx0eXBlbmFtZSAuLi5FbGVtcz4KY2xhc3MgYWxsX3N1YnNldHM8c2V0PEVsZW1zLi4uPj4gewpwdWJsaWM6CiAgICB0eXBlZGVmIHR5cGVuYW1lIGFsbF9zdWJzZXRzX3dvcmtlcjxzZXQ8RWxlbXMuLi4+LCBzZXQ8Pj46OnR5cGUgdHlwZTsKfTsKCgppbnQgbWFpbihpbnQgYXJnYywgY29uc3QgY2hhciAqIGFyZ3ZbXSkKewogICAgYXV0byB0ID0gYWxsX3N1YnNldHM8c2V0PGVsZW1lbnQ8MD4sIGVsZW1lbnQ8MT4sIGVsZW1lbnQ8Mj4sIGVsZW1lbnQ8Mz4+Pjo6dHlwZSgpOwogICAgYXV0byBwID0gYWxsX3N1YnNldHM8c2V0PD4+Ojp0eXBlKCk7CgogICAgcHJpbnQodCk7CgogICAgc3RkOjpjb3V0IDw8ICJcbiI7CgogICAgcHJpbnQocCk7CgogICAgc3RkOjpjb3V0IDw8ICJcbiI7CgogICAgcmV0dXJuIDA7Cn0=
{{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}}
{{}}