I am trying to concatenate string_views at compile-time. With the help of this post, I came up with something like this:
#include <cstddef>
#include <array>
#include <cstring>
#include <string_view>
#include <iostream>
////////////////////////////////////////////////////////////////
template <std::size_t N>
class QObject
{
private:
template <std::size_t S>
friend class QObject;
template <std::size_t S1, std::size_t S2>
constexpr QObject(const std::array<char, S1> s1, const std::array<char, S2> s2)
: _string() {
std::copy(s1.begin(), s1.end() - 1, _string.begin());
std::copy(s2.begin(), s2.end() - 1, _string.begin() + S1 - 1);
}
public:
std::array<char, N> _string; // has to be public for 'auto...' to work!
constexpr QObject(const char (&str)[N]) : _string() {
std::copy(&str[0], &str[0] + N, _string.begin());
}
constexpr QObject(std::string_view str) : _string() {
std::copy(str.data(), str.data() + N, _string.begin());
}
template <std::size_t S>
constexpr auto operator+(const QObject<S> other) const {
return QObject<N + other._string.size() - 1>(_string, other._string);
}
[[nodiscard]]
constexpr auto c_str() const {
return _string.data();
}
};
template <auto FIRST, auto... REST>
constexpr auto cconcat_impl() {
if constexpr (!sizeof...(REST)) { return FIRST; }
else { return FIRST + cconcat_impl<REST...>(); }
}
template <auto... Ts>
consteval auto cconcat() {
return cconcat_impl<Ts...>();
}
////////////////////////////////////////////////////////////////
constexpr std::string_view value = "Edward";
int main() {
constexpr auto joined = cconcat<QObject{"name="}, QObject<7>{value}>();
std::cout << joined.c_str() << std::endl;
return 0;
}
However, having to write the number of characters explicitly is pain. value
is constexpr, its size is fixed. It seems ridiculous that I have to count the characters myself and write that number explicitly. Surely, there must be a way to avoid that? I know I could use constexpr const char value[] = "Edward";
instead of std::string_view
, but I have to work with const char*
s. Does anybody have a way to avoid this?