Skip to content

Instantly share code, notes, and snippets.

@daniel-j-h
Created July 15, 2016 21:42
Show Gist options
  • Save daniel-j-h/6bc186ff832647bb128895534fce61bb to your computer and use it in GitHub Desktop.
Save daniel-j-h/6bc186ff832647bb128895534fce61bb to your computer and use it in GitHub Desktop.
Compile-time strings and string concatenation
#include <stdexcept>
#include <utility>
class Str {
public:
template <std::size_t N>
constexpr Str(const char(&a)[N]) : p(a), s(N - 1) {}
constexpr char operator[](std::size_t n) const {
return n < s ? p[n] : throw std::out_of_range("Str::operator[]");
}
constexpr std::size_t size() const {
return s;
}
private:
const char* const p;
const std::size_t s;
};
template <typename... Strs>
class StrList {
public:
constexpr StrList(Strs... strs) : list{strs...} {}
constexpr Str operator[](std::size_t n) const {
return n < (sizeof...(Strs)) ? list[n] : throw std::out_of_range("StrList::operator[]");
}
constexpr std::size_t size() const {
return do_size(0, sizeof...(Strs));
}
constexpr StrList<Strs..., Str> operator+(Str r) {
return do_add(std::index_sequence_for<Strs...>{}, r);
}
private:
const Str list[sizeof...(Strs)];
constexpr std::size_t do_size(std::size_t a, std::size_t n) const {
return n == 0 ? a : do_size(a + list[n - 1].size(), n - 1);
}
template <std::size_t... I>
constexpr auto do_add(std::index_sequence<I...>, Str r) -> StrList<Strs..., Str> {
return StrList<Strs..., Str>(list[I]..., r);
}
};
constexpr auto operator+(Str l, Str r) -> StrList<Str, Str> {
return StrList<Str, Str>(l, r);
}
int main() {
constexpr auto x = Str("ab") + Str("cd") + Str("ef");
constexpr auto ab = x[0];
static_assert(ab[0] == 'a', "");
static_assert(ab[1] == 'b', "");
return x.size(); // compiles down to ret 6
}
@daniel-j-h
Copy link
Author

Aaand compile-time hashing of compile-time strings.

#include <cstdint>
#include <utility>
#include <stdexcept>


class Str {
public:
  template <std::size_t N>
  constexpr Str(const char(&a)[N]) : p(a), s(N - 1) {}

  constexpr char operator[](std::size_t n) const {
    return n < s ? p[n] : throw std::out_of_range("Str::operator[]");
  }

  constexpr std::size_t size() const {
    return s;
  }

private:
  const char* const p;
  const std::size_t s;
};


// compile-time djb2 hash
constexpr std::uint64_t hash_value(Str str) {
  std::uint64_t hash = 5381;
  int c = 0;

  for (std::size_t i{0}; i < str.size(); ++i) {
    c = str[i]; // char to int conversion
    hash = ((hash << 5) + hash) + c;
  }

  return hash;
}


int main() {
  const constexpr Str s{"Hello World"};

  static_assert(hash_value(s) == 13827776004929097857ull, "");
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment