int main() { return 0; }
#include <iostream>
#pragma mark Definition: Boolean
struct True { };
struct False { };
#pragma mark Definition: Equality
namespace {
template <typename, typename>
struct eq_impl { using type = False; };
template <typename A>
struct eq_impl<A, A> { using type = True; };
};
template <typename A, typename B>
using Equal = typename eq_impl<A, B>::type;
#pragma mark Definition: Natural Number
struct Zero {};
template <typename>
struct S {};
template <typename>
struct Eval;
template <>
struct Eval<Zero> {
static constexpr int value = 0;
};
template <typename Num>
struct Eval<S<Num>> {
static constexpr int value = 1 + Eval<Num>::value;
};
std::ostream &operator<<(std::ostream &os, const Zero &) {
os << Eval<Zero>::value;
return os;
}
template <typename Num>
std::ostream &operator<<(std::ostream &os, const S<Num> &) {
os << Eval<S<Num>>::value;
return os;
}
#pragma mark Definition: If
namespace {
template <typename Condition, typename Then, typename Else>
struct if_impl;
template <typename Then, typename Else>
struct if_impl<True, Then, Else> {
using type = Then;
};
template <typename Then, typename Else>
struct if_impl<False, Then, Else> {
using type = Else;
};
};
template <typename Condition, typename Then, typename Else>
using If = typename if_impl<Condition, Then, Else>::type;
#pragma mark Definition: Or
namespace {
template <typename, typename>
struct or_impl {
using type = True;
};
template <>
struct or_impl<False, False> {
using type = False;
};
};
template <typename P, typename Q>
using Or = typename or_impl<P, Q>::type;
#pragma mark Utility
namespace {
template <int n>
struct make_num_impl {
using type = S<typename make_num_impl<n - 1>::type>;
};
template <>
struct make_num_impl<0> {
using type = Zero;
};
};
template <int n>
using MakeNum = typename make_num_impl<n>::type;
struct Stop {};
struct Nothing {};
std::ostream &operator<<(std::ostream &os, const Nothing *) { return os; };
struct LineBreak { LineBreak() { std::cout << std::endl; } };
template <typename X, typename Y, typename T>
using Enable = If<Equal<X, Y>, Stop, T>;
#pragma mark Implementation of Fizz / Buzz
#define DefineFizzBuzz(Name, ...)\
template <typename Num, typename C = Zero> struct Name;\
template <typename Num, typename C> struct Name<S<Num>, C> : public Name<Num, If<Equal<C, __VA_ARGS__>, Zero, S<C>>> {};\
template <typename C> struct Name<Zero, C> { using is_enable = Equal<C, Zero>;\
Name() { std::cout << static_cast<If<is_enable, Name, Nothing> *>(nullptr); };\
};\
template <typename Num, typename C> std::ostream &operator<<(std::ostream &os, const Name<Num, C> *) {\
os << #Name;\
return os;\
};
DefineFizzBuzz(Fizz, S<S<Zero>>);
DefineFizzBuzz(Buzz, S<S<S<S<Zero>>>>);
#pragma mark Implementation of Number
template <typename> struct number_impl;
template <typename Num>
struct number_impl {
number_impl() { std::cout << Num(); }
};
template <typename Num>
using Number = If<Or<typename Fizz<Num>::is_enable, typename Buzz<Num>::is_enable>, Nothing, number_impl<Num>>;
#pragma mark FizzBuzz Composition
template <typename Num, typename Max>
struct fizz_buzz_impl : public
Fizz<Num>
, Buzz<Num>
, Number<Num>
, LineBreak
, Enable<Num, Max, fizz_buzz_impl<S<Num>, Max>> { };
template <int n>
using FizzBuzz = fizz_buzz_impl<S<Zero>, MakeNum<n>>;
FizzBuzz<20> fizzbuzz;
aW50IG1haW4oKSB7IHJldHVybiAwOyB9CiAKI2luY2x1ZGUgPGlvc3RyZWFtPgogCiNwcmFnbWEgbWFyayBEZWZpbml0aW9uOiBCb29sZWFuCiAKc3RydWN0IFRydWUgeyB9OwpzdHJ1Y3QgRmFsc2UgeyB9OwogCiNwcmFnbWEgbWFyayBEZWZpbml0aW9uOiBFcXVhbGl0eQogCm5hbWVzcGFjZSB7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUsIHR5cGVuYW1lPgogICAgc3RydWN0IGVxX2ltcGwgeyB1c2luZyB0eXBlID0gRmFsc2U7IH07CiAKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBBPgogICAgc3RydWN0IGVxX2ltcGw8QSwgQT4geyB1c2luZyB0eXBlID0gVHJ1ZTsgfTsKfTsKIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgQSwgdHlwZW5hbWUgQj4KdXNpbmcgRXF1YWwgPSB0eXBlbmFtZSBlcV9pbXBsPEEsIEI+Ojp0eXBlOwogCiNwcmFnbWEgbWFyayBEZWZpbml0aW9uOiBOYXR1cmFsIE51bWJlcgogCnN0cnVjdCBaZXJvIHt9Owp0ZW1wbGF0ZSA8dHlwZW5hbWU+CnN0cnVjdCBTIHt9OwogCnRlbXBsYXRlIDx0eXBlbmFtZT4Kc3RydWN0IEV2YWw7CiAKdGVtcGxhdGUgPD4Kc3RydWN0IEV2YWw8WmVybz4gewogICAgc3RhdGljIGNvbnN0ZXhwciBpbnQgdmFsdWUgPSAwOwp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgTnVtPgpzdHJ1Y3QgRXZhbDxTPE51bT4+IHsKICAgIHN0YXRpYyBjb25zdGV4cHIgaW50IHZhbHVlID0gMSArIEV2YWw8TnVtPjo6dmFsdWU7Cn07CiAKc3RkOjpvc3RyZWFtICZvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSAmb3MsIGNvbnN0IFplcm8gJikgewogICAgb3MgPDwgRXZhbDxaZXJvPjo6dmFsdWU7CiAgICByZXR1cm4gb3M7Cn0KIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgTnVtPgpzdGQ6Om9zdHJlYW0gJm9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtICZvcywgY29uc3QgUzxOdW0+ICYpIHsKICAgIG9zIDw8IEV2YWw8UzxOdW0+Pjo6dmFsdWU7CiAgICByZXR1cm4gb3M7Cn0KIAojcHJhZ21hIG1hcmsgRGVmaW5pdGlvbjogSWYKIApuYW1lc3BhY2UgewogICAgdGVtcGxhdGUgPHR5cGVuYW1lIENvbmRpdGlvbiwgdHlwZW5hbWUgVGhlbiwgdHlwZW5hbWUgRWxzZT4KICAgIHN0cnVjdCBpZl9pbXBsOwogCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVGhlbiwgdHlwZW5hbWUgRWxzZT4KICAgIHN0cnVjdCBpZl9pbXBsPFRydWUsIFRoZW4sIEVsc2U+IHsKICAgICAgICB1c2luZyB0eXBlID0gVGhlbjsKICAgIH07CiAKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUaGVuLCB0eXBlbmFtZSBFbHNlPgogICAgc3RydWN0IGlmX2ltcGw8RmFsc2UsIFRoZW4sIEVsc2U+IHsKICAgICAgICB1c2luZyB0eXBlID0gRWxzZTsKICAgIH07Cn07CiAKdGVtcGxhdGUgPHR5cGVuYW1lIENvbmRpdGlvbiwgdHlwZW5hbWUgVGhlbiwgdHlwZW5hbWUgRWxzZT4KdXNpbmcgSWYgPSB0eXBlbmFtZSBpZl9pbXBsPENvbmRpdGlvbiwgVGhlbiwgRWxzZT46OnR5cGU7CiAKI3ByYWdtYSBtYXJrIERlZmluaXRpb246IE9yCiAKbmFtZXNwYWNlIHsKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSwgdHlwZW5hbWU+CiAgICBzdHJ1Y3Qgb3JfaW1wbCB7CiAgICAgICAgdXNpbmcgdHlwZSA9IFRydWU7CiAgICB9OwogCiAgICB0ZW1wbGF0ZSA8PgogICAgc3RydWN0IG9yX2ltcGw8RmFsc2UsIEZhbHNlPiB7CiAgICAgICAgdXNpbmcgdHlwZSA9IEZhbHNlOwogICAgfTsKfTsKIAp0ZW1wbGF0ZSA8dHlwZW5hbWUgUCwgdHlwZW5hbWUgUT4KdXNpbmcgT3IgPSB0eXBlbmFtZSBvcl9pbXBsPFAsIFE+Ojp0eXBlOwogCiNwcmFnbWEgbWFyayBVdGlsaXR5CiAKbmFtZXNwYWNlIHsKICAgIHRlbXBsYXRlIDxpbnQgbj4KICAgIHN0cnVjdCBtYWtlX251bV9pbXBsIHsKICAgICAgICB1c2luZyB0eXBlID0gUzx0eXBlbmFtZSBtYWtlX251bV9pbXBsPG4gLSAxPjo6dHlwZT47CiAgICB9OwogCiAgICB0ZW1wbGF0ZSA8PgogICAgc3RydWN0IG1ha2VfbnVtX2ltcGw8MD4gewogICAgICAgIHVzaW5nIHR5cGUgPSBaZXJvOwogICAgfTsKfTsKIAp0ZW1wbGF0ZSA8aW50IG4+CnVzaW5nIE1ha2VOdW0gPSB0eXBlbmFtZSBtYWtlX251bV9pbXBsPG4+Ojp0eXBlOwogCnN0cnVjdCBTdG9wIHt9OwogCnN0cnVjdCBOb3RoaW5nIHt9OwpzdGQ6Om9zdHJlYW0gJm9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtICZvcywgY29uc3QgTm90aGluZyAqKSB7IHJldHVybiBvczsgfTsKIApzdHJ1Y3QgTGluZUJyZWFrIHsgTGluZUJyZWFrKCkgeyBzdGQ6OmNvdXQgPDwgc3RkOjplbmRsOyB9IH07CiAKdGVtcGxhdGUgPHR5cGVuYW1lIFgsIHR5cGVuYW1lIFksIHR5cGVuYW1lIFQ+CnVzaW5nIEVuYWJsZSA9IElmPEVxdWFsPFgsIFk+LCBTdG9wLCBUPjsKIAojcHJhZ21hIG1hcmsgSW1wbGVtZW50YXRpb24gb2YgRml6eiAvIEJ1enoKIAojZGVmaW5lIERlZmluZUZpenpCdXp6KE5hbWUsIC4uLilcCnRlbXBsYXRlIDx0eXBlbmFtZSBOdW0sIHR5cGVuYW1lIEMgPSBaZXJvPiBzdHJ1Y3QgTmFtZTtcCnRlbXBsYXRlIDx0eXBlbmFtZSBOdW0sIHR5cGVuYW1lIEM+IHN0cnVjdCBOYW1lPFM8TnVtPiwgQz4gOiBwdWJsaWMgTmFtZTxOdW0sIElmPEVxdWFsPEMsIF9fVkFfQVJHU19fPiwgWmVybywgUzxDPj4+IHt9O1wKdGVtcGxhdGUgPHR5cGVuYW1lIEM+IHN0cnVjdCBOYW1lPFplcm8sIEM+IHsgdXNpbmcgaXNfZW5hYmxlID0gRXF1YWw8QywgWmVybz47XAogICAgTmFtZSgpIHsgc3RkOjpjb3V0IDw8IHN0YXRpY19jYXN0PElmPGlzX2VuYWJsZSwgTmFtZSwgTm90aGluZz4gKj4obnVsbHB0cik7IH07XAp9O1wKdGVtcGxhdGUgPHR5cGVuYW1lIE51bSwgdHlwZW5hbWUgQz4gc3RkOjpvc3RyZWFtICZvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSAmb3MsIGNvbnN0IE5hbWU8TnVtLCBDPiAqKSB7XAogICAgb3MgPDwgI05hbWU7XAogICAgcmV0dXJuIG9zO1wKfTsKIApEZWZpbmVGaXp6QnV6eihGaXp6LCBTPFM8WmVybz4+KTsKRGVmaW5lRml6ekJ1enooQnV6eiwgUzxTPFM8UzxaZXJvPj4+Pik7CiAKI3ByYWdtYSBtYXJrIEltcGxlbWVudGF0aW9uIG9mIE51bWJlcgogCnRlbXBsYXRlIDx0eXBlbmFtZT4gc3RydWN0IG51bWJlcl9pbXBsOwogCnRlbXBsYXRlIDx0eXBlbmFtZSBOdW0+CnN0cnVjdCBudW1iZXJfaW1wbCB7CiAgICBudW1iZXJfaW1wbCgpIHsgc3RkOjpjb3V0IDw8IE51bSgpOyB9Cn07CiAKdGVtcGxhdGUgPHR5cGVuYW1lIE51bT4KdXNpbmcgTnVtYmVyID0gSWY8T3I8dHlwZW5hbWUgRml6ejxOdW0+Ojppc19lbmFibGUsIHR5cGVuYW1lIEJ1eno8TnVtPjo6aXNfZW5hYmxlPiwgTm90aGluZywgbnVtYmVyX2ltcGw8TnVtPj47CiAKI3ByYWdtYSBtYXJrIEZpenpCdXp6IENvbXBvc2l0aW9uCiAKdGVtcGxhdGUgPHR5cGVuYW1lIE51bSwgdHlwZW5hbWUgTWF4PgpzdHJ1Y3QgZml6el9idXp6X2ltcGwgOiBwdWJsaWMKICBGaXp6PE51bT4KLCBCdXp6PE51bT4KLCBOdW1iZXI8TnVtPgosIExpbmVCcmVhawosIEVuYWJsZTxOdW0sIE1heCwgZml6el9idXp6X2ltcGw8UzxOdW0+LCBNYXg+PiB7IH07CiAKdGVtcGxhdGUgPGludCBuPgp1c2luZyBGaXp6QnV6eiA9IGZpenpfYnV6el9pbXBsPFM8WmVybz4sIE1ha2VOdW08bj4+OwogCkZpenpCdXp6PDIwPiBmaXp6YnV6ejs=