Files
Cpp-in-Embedded-Systems/Chapter18/cib/libs/sc/string_constant.hpp
Amar Mahmutbegovic 8634accda5 add Chapter18
2025-02-06 00:19:59 +01:00

109 lines
3.6 KiB
C++

#pragma once
#include <sc/fwd.hpp>
#include <array>
#include <iterator>
#include <limits>
#include <string_view>
#include <utility>
namespace sc {
template <typename CharT, CharT... chars> struct string_constant {
using value_type = std::basic_string_view<CharT>;
private:
constexpr static std::array<CharT, sizeof...(chars)> storage{chars...};
using size_type = int;
using const_iterator = typename value_type::const_iterator;
constexpr static size_type npos = std::numeric_limits<size_type>::max();
public:
constexpr static value_type value{storage.data(), sizeof...(chars)};
constexpr static auto begin() noexcept { return std::cbegin(storage); }
constexpr static auto end() noexcept { return std::cend(storage); }
[[nodiscard]] constexpr static auto size() noexcept {
return std::size(storage);
}
template <size_type pos = 0, size_type count = npos>
[[nodiscard]] constexpr static auto
substr(std::integral_constant<size_type, pos>,
std::integral_constant<size_type, count> = {}) {
constexpr size_type sz = count == npos ? size() - pos : count;
return [&]<size_type... Is>(std::integer_sequence<size_type, Is...>) {
return string_constant<CharT, storage[pos + Is]...>{};
}(std::make_integer_sequence<size_type, sz>{});
}
template <typename F> constexpr auto apply(F &&f) const {
return std::forward<F>(f)(*this);
}
};
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator==(string_constant<CharT, charsLhs...>,
string_constant<CharT, charsRhs...>) noexcept -> bool {
return false;
}
template <class CharT, CharT... chars>
[[nodiscard]] constexpr auto
operator==(string_constant<CharT, chars...>,
string_constant<CharT, chars...>) noexcept -> bool {
return true;
}
#if __cpp_lib_three_way_comparison < 201907L
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator!=(string_constant<CharT, charsLhs...> lhs,
string_constant<CharT, charsRhs...> rhs) noexcept -> bool {
return not(lhs == rhs);
}
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator<(string_constant<CharT, charsLhs...> lhs,
string_constant<CharT, charsRhs...> rhs) noexcept -> bool {
return lhs.value < rhs.value;
}
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator>(string_constant<CharT, charsLhs...> lhs,
string_constant<CharT, charsRhs...> rhs) noexcept -> bool {
return lhs.value > rhs.value;
}
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator<=(string_constant<CharT, charsLhs...> lhs,
string_constant<CharT, charsRhs...> rhs) noexcept -> bool {
return lhs.value <= rhs.value;
}
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator>=(string_constant<CharT, charsLhs...> lhs,
string_constant<CharT, charsRhs...> rhs) noexcept -> bool {
return lhs.value >= rhs.value;
}
#else
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator<=>(string_constant<CharT, charsLhs...> lhs,
string_constant<CharT, charsRhs...> rhs) noexcept {
return lhs.value <=> rhs.value;
}
#endif
template <class CharT, CharT... charsLhs, CharT... charsRhs>
[[nodiscard]] constexpr auto
operator+(string_constant<CharT, charsLhs...>,
string_constant<CharT, charsRhs...>) noexcept
-> string_constant<CharT, charsLhs..., charsRhs...> {
return {};
}
} // namespace sc