Skip to content

Instantly share code, notes, and snippets.

@ecatmur
Last active May 7, 2021 14:42
Show Gist options
  • Save ecatmur/ef86d7a3277bdba4fc7b24e5fdb4d2ac to your computer and use it in GitHub Desktop.
Save ecatmur/ef86d7a3277bdba4fc7b24e5fdb4d2ac to your computer and use it in GitHub Desktop.
Constexpr string processing and dropping to runtime via std::array
#include <array>
#include <iostream>
#include <string>
#include <utility>
#if __cpp_lib_constexpr_string >= 201907L
using string = std::string;
#else
struct string {
using value_type = char;
char* ptr = nullptr;
unsigned z = 0, cap = 0;
constexpr string(string&& r)
: ptr(std::exchange(r.ptr, nullptr))
, z(std::exchange(r.z, 0))
, cap(std::exchange(r.cap, 0)) {}
constexpr ~string() { delete[] ptr; }
constexpr string(char const* s) {
while (s[cap++]);
for (ptr = new char[cap]; z != cap; ++z) ptr[z] = s[z];
}
constexpr string(char const* c, char const* d) {
while (c + cap++ != d);
for (ptr = new char[cap]; z != cap; ++z) ptr[z] = c + z == d ? 0 : c[z];
}
constexpr char& operator[](unsigned n) { return ptr[n]; }
constexpr char operator[](unsigned n) const { return ptr[n]; }
constexpr unsigned size() const { return z; }
constexpr char const* data() const { return ptr; }
constexpr char const* begin() const { return ptr; }
constexpr char const* end() const { return ptr + z; }
};
inline std::ostream& operator<<(std::ostream& os, string const& s) {
return os << std::string(s.begin(), s.end());
}
#endif
template<class T, unsigned N>
struct flat : std::array<typename T::value_type, N> {
constexpr operator T() const { return T(this->begin(), this->end()); }
constexpr T value() const { return *this; }
template<class It, std::size_t... I>
constexpr flat(It it, std::index_sequence<I...>) : flat::array{(I, *it++)...} {}
};
template<auto f>
constexpr auto flatten() {
constexpr unsigned N = f().size();
return flat<decltype(f()), N>(f().begin(), std::make_index_sequence<N>());
}
constexpr string f() {
// string processing at compile time!
auto s = string("hello");
++s[0];
return s;
}
template<flat a>
void g() {
auto s = a.value();
++s[0];
std::cout << s << std::endl;
}
int main() {
g<flatten<[] { return f(); }>()>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment