1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
#include <type_traits>
#include <utility>
#include <iterator>
#include <iostream>
#define O(type) \
template <type N> \
using type##_c = std::integral_constant<type, N>; \
template <type N> \
constexpr type##_c<N> type##_v{} \
/**/
O(char); O(unsigned);
#undef O
template <char... Cs>
constexpr char data_v[sizeof...(Cs)] = { Cs... };
template <char... Cs>
struct literal_string
{
constexpr static std::size_t size() noexcept { return sizeof...(Cs); }
constexpr static char const* data() noexcept { return data_v<Cs...>; }
constexpr char const& operator[](std::size_t N) const
{ return data()[N]; }
};
template <char C, char... Cs>
constexpr auto push_front(char_c<C>, literal_string<Cs...>)
{ return literal_string<C, Cs...>{}; }
namespace detail::string
{
template <typename S>
constexpr auto indices_for(S&& s)
{ return std::make_index_sequence<sizeof(s)>(); }
template <typename MS, std::size_t... Is>
constexpr auto bind_literal_string(MS m, std::index_sequence<Is...>)
{ return literal_string<m()[Is]...>{}; }
}
#define CT_LITERAL_STRING(lit) \
([]() { \
return detail::string::bind_literal_string \
([]() -> auto& { return lit; }, detail::string::indices_for(lit)); \
}()) \
/**/
namespace detail::prepend
{
template <unsigned N, typename Tail>
struct prepend_number_impl
{
using type = prepend_number_impl
<N / 10, decltype(push_front(char_v<(N % 10) + '0'>, Tail{}))>;
};
template <typename Tail>
struct prepend_number_impl<0, Tail>
{ using type = Tail; };
}
template <unsigned N, typename Tail>
using prepend_number_t = typename detail::prepend::prepend_number_impl
<N / 10, decltype(push_front(char_v<(N % 10) + '0'>, Tail{}))>::type;
template <unsigned N, typename Tail>
constexpr auto prepend_number(unsigned_c<N>, Tail)
{ return prepend_number_t<N, Tail>{}; }
template <typename String>
constexpr auto encoded_string(String s)
{
return prepend_number
(unsigned_v<s.size() - 1>, push_front(char_v<':'>, s));
}
int main()
{
constexpr auto es = encoded_string(CT_LITERAL_STRING("foobar"));
std::cout << es.data() << '\n';
}
|