Skip to content

Instantly share code, notes, and snippets.

@notfoundry
Created July 20, 2019 02:16
Show Gist options
  • Select an option

  • Save notfoundry/835b4f3db275a54262dbf8d29bb64933 to your computer and use it in GitHub Desktop.

Select an option

Save notfoundry/835b4f3db275a54262dbf8d29bb64933 to your computer and use it in GitHub Desktop.
cpp_constexpr_string_interpolation
#include <boost/mp11/map.hpp>
#include <boost/mp11/list.hpp>
namespace ct {
using namespace boost::mp11;
template <class C, C... Cs>
struct nttp_string {
constexpr static C data[sizeof...(Cs)] = {Cs...};
constexpr static auto value = []{ return data; };
constexpr static char const* c_str() noexcept {
return data;
}
};
template <class S1, class S2>
struct nttp_string_concat;
template <class C, C... S1Cs, C... S2Cs>
struct nttp_string_concat<nttp_string<C, S1Cs...>, nttp_string<C, S2Cs...>> {
using type = nttp_string<C, S1Cs..., S2Cs...>;
};
enum class state {
waiting_for_opener,
waiting_for_closer
};
template <class Format, class Table, class Result, class Key, state State = state::waiting_for_opener>
struct nttp_string_formatter_impl;
template <class C, class Table, C... ResultCs, class Key>
struct nttp_string_formatter_impl<nttp_string<C>, Table, nttp_string<C, ResultCs...>, Key, state::waiting_for_opener> {
constexpr static auto value = nttp_string<C, ResultCs...>();
};
template <class C, C Front, C... FormatCs, class Table, C... ResultCs, class Key>
struct nttp_string_formatter_impl<nttp_string<C, Front, FormatCs...>, Table, nttp_string<C, ResultCs...>, Key, state::waiting_for_opener> {
constexpr static auto value = nttp_string_formatter_impl<
nttp_string<C, FormatCs...>, Table, nttp_string<C, ResultCs..., Front>, Key, state::waiting_for_opener
>::value;
};
template <class C, C... FormatCs, class Table, C... ResultCs, class Key>
struct nttp_string_formatter_impl<nttp_string<C, C('{'), FormatCs...>, Table, nttp_string<C, ResultCs...>, Key, state::waiting_for_opener> {
constexpr static auto value = nttp_string_formatter_impl<
nttp_string<C, FormatCs...>, Table, nttp_string<C, ResultCs...>, nttp_string<C>, state::waiting_for_closer
>::value;
};
template <class C, C Front, C... FormatCs, class Table, class Result, C... KeyCs>
struct nttp_string_formatter_impl<nttp_string<C, Front, FormatCs...>, Table, Result, nttp_string<C, KeyCs...>, state::waiting_for_closer> {
constexpr static auto value = nttp_string_formatter_impl<
nttp_string<C, FormatCs...>, Table, Result, nttp_string<C, KeyCs..., Front>, state::waiting_for_closer
>::value;
};
template <class C, C... FormatCs, class Table, class Result, C... KeyCs>
struct nttp_string_formatter_impl<nttp_string<C, C('}'), FormatCs...>, Table, Result, nttp_string<C, KeyCs...>, state::waiting_for_closer> {
using substitution = mp_second<mp_map_find<Table, nttp_string<C, KeyCs...>>>;
constexpr static auto value = nttp_string_formatter_impl<
nttp_string<C, FormatCs...>, Table, typename nttp_string_concat<Result, substitution>::type, nttp_string<C, KeyCs...>, state::waiting_for_opener
>::value;
};
template <class Format, class Table>
struct nttp_string_formatter;
template <class C, C... Cs, class Table>
struct nttp_string_formatter<nttp_string<C, Cs...>, Table> {
constexpr static auto value = nttp_string_formatter_impl<nttp_string<C, Cs...>, Table, nttp_string<C>, nttp_string<C>>::value;
};
template <class Format, class Table = mp_list<>>
struct formatted_nttp_string_builder {
template <class Key, class Value>
constexpr auto operator()(Key, Value) {
return formatted_nttp_string_builder<Format, mp_map_insert<Table, mp_list<Key, Value>>>();
}
constexpr auto operator()() {
return nttp_string_formatter<Format, Table>::value;
}
};
namespace string_literals {
template <class C, C... Cs>
constexpr auto operator""_s() noexcept {
return nttp_string<C, Cs...>();
}
template <class C, C... Cs>
constexpr auto operator""_f() noexcept {
return formatted_nttp_string_builder<nttp_string<C, Cs...>>();
}
}
}
using namespace ct::string_literals;
constexpr auto s = "Hello {name}, today is {date}!"_f("name"_s, "Foo"_s)("date"_s, "Friday"_s)();
char const* cs = s.c_str();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment