Skip to content

Instantly share code, notes, and snippets.

@xsduan
Created July 10, 2020 02:30
Show Gist options
  • Save xsduan/638b62591a6d5b06536cfe9d29e2006c to your computer and use it in GitHub Desktop.
Save xsduan/638b62591a6d5b06536cfe9d29e2006c to your computer and use it in GitHub Desktop.
#include <iostream>
#include <utility>
// ----- prelude -----
// --- control flow ---
// ~~ if ~~
// control flow
template <bool cond, typename then_res, typename else_res> struct __if;
template <typename then_res, typename else_res>
struct __if<true, then_res, else_res> {
using then = then_res;
};
template <typename then_res, typename else_res>
struct __if<false, then_res, else_res> {
using then = else_res;
};
// --- boolean ---
// ~~ and ~~
// logical and
template <bool p, bool q> struct __and {
enum { val = true };
};
template <bool p> struct __and<p, false> {
enum { val = false };
};
template <bool q> struct __and<false, q> {
enum { val = false };
};
template <> struct __and<false, false> {
enum { val = false };
};
// ~~ or ~~
// logical or
template <bool p, bool q> struct __or {
enum { val = true };
};
template <bool p> struct __or<p, false> {
enum { val = true };
};
template <bool q> struct __or<false, q> {
enum { val = true };
};
template <> struct __or<false, false> {
enum { val = false };
};
// --- binary cmp ---
// ~~ eq ~~
// equals to
template <char l, char r> struct __eq {
enum { val = __eq<l - 1, r - 1>::val };
};
template <char l> struct __eq<l, 0> {
enum { val = false };
};
template <char r> struct __eq<0, r> {
enum { val = false };
};
template <> struct __eq<0, 0> {
enum { val = true };
};
// ~~ gt ~~
// greater than
template <char l, char r> struct __gt {
enum { val = __gt<l - 1, r - 1>::val };
};
//
template <char l> struct __gt<l, 0> {
enum { val = true };
};
template <char r> struct __gt<0, r> {
enum { val = false };
};
template <> struct __gt<0, 0> {
enum { val = false };
};
// ~~ gte ~~
// greater than or equals
template <char l, char r> struct __gte {
enum { val = __or<__gt<l, r>::val, __eq<l, r>::val>::val };
};
// ~~ lte ~~
// less than or equals
template <char l, char r> struct __lte {
enum { val = __gte<r, l>::val };
};
// --- arithmetic ---
// ~~ add ~~
// integer addition
template <char l, char r> struct __add {
enum { val = __add<l + 1, r - 1>::val };
};
template <char l> struct __add<l, 0> {
enum { val = l };
};
// --- misc ---
// ~~ str ~~
// accumulate char params into a string
template <char... chars> struct __str {
static constexpr char val[]{chars..., '\0'};
};
namespace impl {
// ~~ cat ~~
// concatenate template strings
template <typename... p> struct __cat { using type = __str<>; };
template <typename a, typename b, typename... p> struct __cat<a, b, p...> {
using res = __cat<typename __cat<a, b>::res, p...>;
};
template <char... a, char... b> struct __cat<__str<a...>, __str<b...>> {
using res = __str<a..., b...>;
};
template <char... a> struct __cat<__str<a...>> { using res = __str<a...>; };
template <typename t> struct __cat<t> { using res = t; };
// ~~ repeat ~~
// repeat `c` `reps` times into `acc`
template <typename c, int reps, typename acc> struct __repeat {
using res = __str<>;
};
template <char c, int reps, char... acc>
struct __repeat<__str<c>, reps, __str<acc...>> {
using res = typename __repeat<__str<c>, reps - 1, __str<c, acc...>>::res;
};
template <char c, char... acc> struct __repeat<__str<c>, 1, __str<acc...>> {
using res = __str<c, acc...>;
};
} // namespace impl
template <typename... p> using __cat = typename impl::__cat<p...>::res;
template <typename c, int reps, typename acc>
using __repeat = typename impl::__repeat<c, reps, acc>::res;
// ----- end prelude -----
template <char c> struct num_map { using res = __str<'?'>; };
template <> struct num_map<'.'> { using res = __str<'1'>; };
template <> struct num_map<','> {
using res = __repeat<__str<'1'>, 2, __str<>>;
};
template <> struct num_map<'?'> {
using res = __repeat<__str<'1'>, 3, __str<>>;
};
template <> struct num_map<'!'> {
using res = __repeat<__str<'1'>, 4, __str<>>;
};
template <> struct num_map<'1'> {
using res = __repeat<__str<'1'>, 5, __str<>>;
};
template <> struct num_map<'a'> { using res = __str<'2'>; };
template <> struct num_map<'b'> {
using res = __repeat<__str<'2'>, 2, __str<>>;
};
template <> struct num_map<'c'> {
using res = __repeat<__str<'2'>, 3, __str<>>;
};
template <> struct num_map<'2'> {
using res = __repeat<__str<'2'>, 4, __str<>>;
};
template <> struct num_map<'d'> { using res = __str<'3'>; };
template <> struct num_map<'e'> {
using res = __repeat<__str<'3'>, 2, __str<>>;
};
template <> struct num_map<'f'> {
using res = __repeat<__str<'3'>, 3, __str<>>;
};
template <> struct num_map<'3'> {
using res = __repeat<__str<'3'>, 4, __str<>>;
};
template <> struct num_map<'g'> { using res = __str<'4'>; };
template <> struct num_map<'h'> {
using res = __repeat<__str<'4'>, 2, __str<>>;
};
template <> struct num_map<'i'> {
using res = __repeat<__str<'4'>, 3, __str<>>;
};
template <> struct num_map<'4'> {
using res = __repeat<__str<'4'>, 4, __str<>>;
};
template <> struct num_map<'j'> { using res = __str<'5'>; };
template <> struct num_map<'k'> {
using res = __repeat<__str<'5'>, 2, __str<>>;
};
template <> struct num_map<'l'> {
using res = __repeat<__str<'5'>, 3, __str<>>;
};
template <> struct num_map<'5'> {
using res = __repeat<__str<'5'>, 4, __str<>>;
};
template <> struct num_map<'m'> { using res = __str<'6'>; };
template <> struct num_map<'n'> {
using res = __repeat<__str<'6'>, 2, __str<>>;
};
template <> struct num_map<'o'> {
using res = __repeat<__str<'6'>, 3, __str<>>;
};
template <> struct num_map<'6'> {
using res = __repeat<__str<'6'>, 4, __str<>>;
};
template <> struct num_map<'p'> { using res = __str<'7'>; };
template <> struct num_map<'q'> {
using res = __repeat<__str<'7'>, 2, __str<>>;
};
template <> struct num_map<'r'> {
using res = __repeat<__str<'7'>, 3, __str<>>;
};
template <> struct num_map<'s'> {
using res = __repeat<__str<'7'>, 4, __str<>>;
};
template <> struct num_map<'7'> {
using res = __repeat<__str<'7'>, 5, __str<>>;
};
template <> struct num_map<'t'> { using res = __str<'8'>; };
template <> struct num_map<'u'> {
using res = __repeat<__str<'8'>, 2, __str<>>;
};
template <> struct num_map<'v'> {
using res = __repeat<__str<'8'>, 3, __str<>>;
};
template <> struct num_map<'8'> {
using res = __repeat<__str<'8'>, 4, __str<>>;
};
template <> struct num_map<'w'> { using res = __str<'9'>; };
template <> struct num_map<'x'> {
using res = __repeat<__str<'9'>, 2, __str<>>;
};
template <> struct num_map<'y'> {
using res = __repeat<__str<'9'>, 3, __str<>>;
};
template <> struct num_map<'z'> {
using res = __repeat<__str<'9'>, 4, __str<>>;
};
template <> struct num_map<'9'> {
using res = __repeat<__str<'9'>, 5, __str<>>;
};
template <> struct num_map<'\''> { using res = __str<'*'>; };
template <> struct num_map<'-'> {
using res = __repeat<__str<'*'>, 2, __str<>>;
};
template <> struct num_map<'+'> {
using res = __repeat<__str<'*'>, 3, __str<>>;
};
template <> struct num_map<'='> {
using res = __repeat<__str<'*'>, 4, __str<>>;
};
template <> struct num_map<'*'> {
using res = __repeat<__str<'*'>, 5, __str<>>;
};
template <> struct num_map<' '> { using res = __str<'0'>; };
template <> struct num_map<'0'> {
using res = __repeat<__str<'0'>, 2, __str<>>;
};
template <char c> struct parse_char_lower {
using res = typename num_map<c>::res;
};
template <char c> struct parse_char_upper {
using res =
__cat<__str<'#', ' '>, typename parse_char_lower<__add<c, 32>::val>::res>;
};
template <char c> struct parse_char {
using res =
typename __if<__and<__gte<c, 'A'>::val, __lte<c, 'Z'>::val>::val,
parse_char_upper<c>, parse_char_lower<c>>::then::res;
};
template <typename str> struct take_last { static const char val = '\0'; };
template <char first, char... acc> struct take_last<__str<first, acc...>> {
static const char val = take_last<__str<acc...>>::val;
};
template <char first> struct take_last<__str<first>> {
static const char val = first;
};
template <typename str> struct take_first { static const char val = '\0'; };
template <char first, char... acc> struct take_first<__str<first, acc...>> {
static const char val = first;
};
template <char a, char b> struct separator {
using res =
typename __if<__eq<take_last<typename parse_char<a>::res>::val,
take_first<typename parse_char<b>::res>::val>::val,
__str<'_'>, __str<' '>>::then;
};
template <typename str> struct letter_map_forward { using res = __str<>; };
template <char a, char b> struct letter_map_forward<__str<a, b>> {
using res = __cat<typename parse_char<a>::res, typename separator<a, b>::res>;
};
template <typename str> struct letter_map { using res = __str<>; };
template <char a, char b, char... acc> struct letter_map<__str<a, b, acc...>> {
using res = __cat<typename letter_map_forward<__str<a, b>>::res,
typename letter_map<__str<b, acc...>>::res>;
};
template <char a, char b> struct letter_map<__str<a, b>> {
using res = __cat<typename letter_map_forward<__str<a, b>>::res,
typename parse_char<b>::res>;
};
template <typename T> void letter_mapify() {
std::cout << "to_t9('" << T::val << "') //" << letter_map<T>::res::val
<< '\n';
}
int main() {
using hello = __str<'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'>;
using hello_caps =
__str<'H', 'E', 'L', 'L', 'O', ' ', 'W', 'O', 'R', 'L', 'D'>;
using abba = __str<'a', 'b', 'b', 'a', ' ', 'f', 'e', 'e', 'd', ' ', 'h', 'i',
'g', 'h'>;
using no_you_dont = __str<'I', ' ', 'l', 'o', 'v', 'e', ' ', 'P', 'H', 'P'>;
using lights = __str<'t', 'h', 'e', 'r', 'e', ' ', 'r', ' ', '4', ' ', 'l',
'i', 'g', 'h', 't', 's', '!'>;
letter_mapify<hello>();
letter_mapify<hello_caps>();
letter_mapify<abba>();
letter_mapify<no_you_dont>();
letter_mapify<lights>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment