#include <ratio>
template <char... Ts>
struct seq;
template <class Seq>
struct parse_sign
{
static constexpr auto sign = intmax_t{1};
using tail = Seq;
};
template <char... Ts>
struct parse_sign<seq<'+', Ts...>>
{
static constexpr auto sign = intmax_t{1};
using tail = seq<Ts...>;
};
template <char... Ts>
struct parse_sign<seq<'-', Ts...>>
{
static constexpr auto sign = intmax_t{-1};
using tail = seq<Ts...>;
};
template <bool BeforePoint, intmax_t Num, intmax_t Den, class Seq>
struct parse_frac;
template <bool BeforePoint, intmax_t Num, intmax_t Den>
struct parse_frac<BeforePoint, Num, Den, seq<>>
{
static constexpr auto num = Num;
static constexpr auto den = Den;
};
template <intmax_t Num, intmax_t Den, char... Ts>
struct parse_frac<true, Num, Den, seq<'.', Ts...>>
{
using next = parse_frac<false, Num, Den, seq<Ts...>>;
static constexpr auto num = next::num;
static constexpr auto den = next::den;
};
template <intmax_t Num, intmax_t Den, char T, char... Ts>
struct parse_frac<true, Num, Den, seq<T, Ts...>>
{
static_assert(
T >= '0' && T <= '9',
"Expected digit."
);
using next = parse_frac<true, 10 * Num + (T - '0'), Den, seq<Ts...>>;
static constexpr auto num = next::num;
static constexpr auto den = next::den;
};
template <intmax_t Num, intmax_t Den, char T, char... Ts>
struct parse_frac<false, Num, Den, seq<T, Ts...>>
{
static_assert(
T >= '0' && T <= '9',
"Expected digit."
);
using next = parse_frac<false, 10 * Num + (T - '0'), 10 * Den, seq<Ts...>>;
static constexpr auto num = next::num;
static constexpr auto den = next::den;
};
template <class Char, Char... Ts>
constexpr auto operator"" _f()
{
using sign_parser = parse_sign<seq<Ts...>>;
using tail = typename sign_parser::tail;
using frac_parser = parse_frac<true, 0, 1, tail>;
return std::ratio<
sign_parser::sign * frac_parser::num,
frac_parser::den
>{};
}
#define cc_fixed(x) decltype(#x ## _f)
int main()
{
using x = cc_fixed(123.456);
using y = cc_fixed(+123.456);
using z = cc_fixed(-123.456);
}
I2luY2x1ZGUgPHJhdGlvPgoKdGVtcGxhdGUgPGNoYXIuLi4gVHM+CnN0cnVjdCBzZXE7Cgp0ZW1wbGF0ZSA8Y2xhc3MgU2VxPgpzdHJ1Y3QgcGFyc2Vfc2lnbgp7CglzdGF0aWMgY29uc3RleHByIGF1dG8gc2lnbiA9IGludG1heF90ezF9OwoJdXNpbmcgdGFpbCA9IFNlcTsKfTsKCnRlbXBsYXRlIDxjaGFyLi4uIFRzPgpzdHJ1Y3QgcGFyc2Vfc2lnbjxzZXE8JysnLCBUcy4uLj4+CnsKCXN0YXRpYyBjb25zdGV4cHIgYXV0byBzaWduID0gaW50bWF4X3R7MX07Cgl1c2luZyB0YWlsID0gc2VxPFRzLi4uPjsKfTsKCnRlbXBsYXRlIDxjaGFyLi4uIFRzPgpzdHJ1Y3QgcGFyc2Vfc2lnbjxzZXE8Jy0nLCBUcy4uLj4+CnsKCXN0YXRpYyBjb25zdGV4cHIgYXV0byBzaWduID0gaW50bWF4X3R7LTF9OwoJdXNpbmcgdGFpbCA9IHNlcTxUcy4uLj47Cn07Cgp0ZW1wbGF0ZSA8Ym9vbCBCZWZvcmVQb2ludCwgaW50bWF4X3QgTnVtLCBpbnRtYXhfdCBEZW4sIGNsYXNzIFNlcT4Kc3RydWN0IHBhcnNlX2ZyYWM7Cgp0ZW1wbGF0ZSA8Ym9vbCBCZWZvcmVQb2ludCwgaW50bWF4X3QgTnVtLCBpbnRtYXhfdCBEZW4+CnN0cnVjdCBwYXJzZV9mcmFjPEJlZm9yZVBvaW50LCBOdW0sIERlbiwgc2VxPD4+CnsKCXN0YXRpYyBjb25zdGV4cHIgYXV0byBudW0gPSBOdW07CglzdGF0aWMgY29uc3RleHByIGF1dG8gZGVuID0gRGVuOwp9OwoKdGVtcGxhdGUgPGludG1heF90IE51bSwgaW50bWF4X3QgRGVuLCBjaGFyLi4uIFRzPgpzdHJ1Y3QgcGFyc2VfZnJhYzx0cnVlLCBOdW0sIERlbiwgc2VxPCcuJywgVHMuLi4+Pgp7Cgl1c2luZyBuZXh0ID0gcGFyc2VfZnJhYzxmYWxzZSwgTnVtLCBEZW4sIHNlcTxUcy4uLj4+OwoJc3RhdGljIGNvbnN0ZXhwciBhdXRvIG51bSA9IG5leHQ6Om51bTsKCXN0YXRpYyBjb25zdGV4cHIgYXV0byBkZW4gPSBuZXh0OjpkZW47Cn07Cgp0ZW1wbGF0ZSA8aW50bWF4X3QgTnVtLCBpbnRtYXhfdCBEZW4sIGNoYXIgVCwgY2hhci4uLiBUcz4Kc3RydWN0IHBhcnNlX2ZyYWM8dHJ1ZSwgTnVtLCBEZW4sIHNlcTxULCBUcy4uLj4+CnsKCXN0YXRpY19hc3NlcnQoCgkJVCA+PSAnMCcgJiYgVCA8PSAnOScsCgkJIkV4cGVjdGVkIGRpZ2l0LiIKCSk7CgoJdXNpbmcgbmV4dCA9IHBhcnNlX2ZyYWM8dHJ1ZSwgMTAgKiBOdW0gKyAoVCAtICcwJyksIERlbiwgc2VxPFRzLi4uPj47CglzdGF0aWMgY29uc3RleHByIGF1dG8gbnVtID0gbmV4dDo6bnVtOwoJc3RhdGljIGNvbnN0ZXhwciBhdXRvIGRlbiA9IG5leHQ6OmRlbjsKfTsKCnRlbXBsYXRlIDxpbnRtYXhfdCBOdW0sIGludG1heF90IERlbiwgY2hhciBULCBjaGFyLi4uIFRzPgpzdHJ1Y3QgcGFyc2VfZnJhYzxmYWxzZSwgTnVtLCBEZW4sIHNlcTxULCBUcy4uLj4+CnsKCXN0YXRpY19hc3NlcnQoCgkJVCA+PSAnMCcgJiYgVCA8PSAnOScsCgkJIkV4cGVjdGVkIGRpZ2l0LiIKCSk7CgoJdXNpbmcgbmV4dCA9IHBhcnNlX2ZyYWM8ZmFsc2UsIDEwICogTnVtICsgKFQgLSAnMCcpLCAxMCAqIERlbiwgc2VxPFRzLi4uPj47CglzdGF0aWMgY29uc3RleHByIGF1dG8gbnVtID0gbmV4dDo6bnVtOwoJc3RhdGljIGNvbnN0ZXhwciBhdXRvIGRlbiA9IG5leHQ6OmRlbjsKfTsKCnRlbXBsYXRlIDxjbGFzcyBDaGFyLCBDaGFyLi4uIFRzPgpjb25zdGV4cHIgYXV0byBvcGVyYXRvciIiIF9mKCkKewoJdXNpbmcgc2lnbl9wYXJzZXIgPSBwYXJzZV9zaWduPHNlcTxUcy4uLj4+OwoJdXNpbmcgdGFpbCA9IHR5cGVuYW1lIHNpZ25fcGFyc2VyOjp0YWlsOwoJdXNpbmcgZnJhY19wYXJzZXIgPSBwYXJzZV9mcmFjPHRydWUsIDAsIDEsIHRhaWw+OwoKCXJldHVybiBzdGQ6OnJhdGlvPAoJCXNpZ25fcGFyc2VyOjpzaWduICogZnJhY19wYXJzZXI6Om51bSwKCQlmcmFjX3BhcnNlcjo6ZGVuCgk+e307Cn0KCiNkZWZpbmUgY2NfZml4ZWQoeCkgZGVjbHR5cGUoI3ggIyMgX2YpCgppbnQgbWFpbigpCnsKCXVzaW5nIHggPSBjY19maXhlZCgxMjMuNDU2KTsKCXVzaW5nIHkgPSBjY19maXhlZCgrMTIzLjQ1Nik7Cgl1c2luZyB6ID0gY2NfZml4ZWQoLTEyMy40NTYpOwp9