I'm learning a bit of metaprogramming in modern C++ and I'm trying to implement a class that should represent string literals/static strings or whatever those are called, in a compile time type. I've managed to get this to work, and I've tried to add some basic compile time operations I want to do with those static strings. Here's the code:
#include <array>
#include <string_view>
#include <utility>
#include <iostream>
template<typename T, T... cs>
class static_string;
template<typename T, T... cs>
constexpr static_string<T, cs...> make_static_string() {
return {};
}
template<typename T, std::size_t N, std::size_t... Is>
constexpr auto make_static_string(const T(&str)[N], std::index_sequence<Is...>) {
return static_string<T, str[Is]...>();
}
template<typename T, std::size_t N>
constexpr auto make_static_string(const T(&str)[N]) {
return make_static_string(str, std::make_index_sequence<N>());
}
template<typename T, T... cs>
class static_string
{
constexpr static std::array<T, sizeof...(cs)> s_data{ cs... };
public:
constexpr static std::basic_string_view<T> value{ s_data.data(), sizeof...(cs) };
};
template<typename T, T... tlhs, T... trhs>
constexpr auto operator+([[maybe_unused]] static_string<T, tlhs...> lhs, [[maybe_unused]] static_string<T, trhs...> rhs) noexcept -> static_string<T, tlhs..., trhs...> {
return {};
}
template <typename T, T... tlhs, size_t N>
constexpr auto operator+(static_string<T, tlhs...> lhs, const T (&rhs)[N]) noexcept {
return lhs + make_static_string(rhs);
}
template <typename T, T... trhs, size_t N>
constexpr auto operator+(const T (&lhs)[N], static_string<T, trhs...> rhs) noexcept {
return make_static_string(lhs) + rhs;
}
template<typename T, T... cs>
constexpr auto operator""_ss() -> static_string<T, cs...> {
return {};
}
int main() {
std::cout << ("Hello"_ss + "World").value;
return 0;
}
With this code I'm able to concatenate literals when I explicitly convert them to my static_string type. However I find that a bit annoying to add my custom string literal operator. I would like to be able to concatenate also my static_string with plain string literals, like "World" in code above.
However I'm struggling with how to convert plain string literal to the parameter pack for my type. This is the problematic part of the code:
template<typename T, std::size_t N, std::size_t... Is>
constexpr auto make_static_string(const T(&str)[N], std::index_sequence<Is...>) {
return static_string<T, str[Is]...>();
}
because str[Is]... cannot really be expanded, as it is not a constant expression. How can one do this properly?
Thanks