fixed_string refactored

This commit is contained in:
Mateusz Pusz
2019-12-23 13:21:48 +01:00
parent e622ecb35a
commit 7cad312b55

View File

@@ -27,85 +27,123 @@
namespace units { namespace units {
template<typename CharT, std::size_t N> template<typename CharT, std::size_t N>
struct basic_fixed_string { struct basic_fixed_string {
CharT data_[N + 1] = {}; CharT data_[N + 1] = {};
constexpr basic_fixed_string(CharT ch) noexcept constexpr basic_fixed_string(CharT ch) noexcept { data_[0] = ch; }
{
data_[0] = ch;
}
constexpr basic_fixed_string(const CharT (&txt)[N + 1]) noexcept constexpr basic_fixed_string(const CharT (&txt)[N + 1]) noexcept
{ {
for(std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i) data_[i] = txt[i];
data_[i] = txt[i]; }
}
[[nodiscard]] constexpr std::size_t size() const noexcept { return N; } [[nodiscard]] constexpr std::size_t size() const noexcept { return N; }
[[nodiscard]] constexpr const CharT* c_str() const noexcept { return data_; } [[nodiscard]] constexpr const CharT* c_str() const noexcept { return data_; }
[[nodiscard]] constexpr const CharT& operator[](std::size_t index) const noexcept { return data_[index]; } [[nodiscard]] constexpr const CharT& operator[](std::size_t index) const noexcept { return data_[index]; }
[[nodiscard]] constexpr CharT operator[](std::size_t index) noexcept { return data_[index]; } [[nodiscard]] constexpr CharT operator[](std::size_t index) noexcept { return data_[index]; }
// auto operator==(const basic_fixed_string &) = default; template<std::size_t N2>
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + N2> operator+(
const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2>& rhs) noexcept
{
CharT txt[N + N2 + 1] = {};
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept for (size_t i = 0; i != N; ++i) txt[i] = lhs[i];
{ for (size_t i = 0; i != N2; ++i) txt[N + i] = rhs[i];
for(size_t i = 0; i != lhs.size(); ++i)
if(lhs.data_[i] != rhs.data_[i])
return false;
return true;
}
template<typename CharT2, std::size_t N2> return units::basic_fixed_string<CharT, N + N2>(txt);
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string&, const basic_fixed_string<CharT2, N2>&) noexcept }
{
return false;
}
template<typename CharT2, std::size_t N2> #if __GNUC__ >= 10
[[nodiscard]] constexpr friend bool operator<(const basic_fixed_string& lhs, const basic_fixed_string<CharT2, N2>& rhs) noexcept
{
using std::begin, std::end;
auto first1 = begin(lhs.data_);
auto first2 = begin(rhs.data_);
const auto last1 = std::prev(end(lhs.data_)); // do not waste time for '\0'
const auto last2 = std::prev(end(rhs.data_));
for(; (first1 != last1) && (first2 != last2); ++first1, (void)++first2 ) { [[nodiscard]] friend constexpr bool operator==(const basic_fixed_string& lhs, const basic_fixed_string& rhs)
if(*first1 < *first2) return true; {
if(*first2 < *first1) return false; for (size_t i = 0; i != lhs.size(); ++i)
if (lhs[i] != rhs[i]) return false;
return true;
}
[[nodiscard]] friend constexpr bool operator!=(const basic_fixed_string&, const basic_fixed_string&) = default;
template<typename CharT2, std::size_t N2>
[[nodiscard]] friend constexpr bool operator==(const basic_fixed_string&, const basic_fixed_string<CharT2, N2>&)
{
return false;
}
template<typename CharT2, std::size_t N2>
// TODO gcc-10 error: a template cannot be defaulted
// [[nodiscard]] friend constexpr bool operator!=(const basic_fixed_string&,
// const basic_fixed_string<CharT2, N2>&) = default;
[[nodiscard]] friend constexpr bool operator!=(const basic_fixed_string&, const basic_fixed_string<CharT2, N2>&)
{
return true;
}
template<typename CharT2, std::size_t N2>
[[nodiscard]] friend constexpr auto operator<=>(const basic_fixed_string& lhs,
const basic_fixed_string<CharT2, N2>& rhs)
{
size_t min_size = std::min(lhs.size(), rhs.size());
for (size_t i = 0; i != min_size; ++i) {
if (auto const cmp = lhs[i] <=> rhs[i]; cmp != 0) {
return cmp;
} }
return first1 == last1 && first2 != last2;
} }
return lhs.size() <=> rhs.size();
}
template<class Traits> #else
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const basic_fixed_string& txt)
{ [[nodiscard]] constexpr friend bool operator==(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept
return os << txt.c_str(); {
for (size_t i = 0; i != lhs.size(); ++i)
if (lhs.data_[i] != rhs.data_[i]) return false;
return true;
}
template<typename CharT2, std::size_t N2>
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string&,
const basic_fixed_string<CharT2, N2>&) noexcept
{
return false;
}
template<typename CharT2, std::size_t N2>
[[nodiscard]] constexpr friend bool operator<(const basic_fixed_string& lhs,
const basic_fixed_string<CharT2, N2>& rhs) noexcept
{
using std::begin, std::end;
auto first1 = begin(lhs.data_);
auto first2 = begin(rhs.data_);
const auto last1 = std::prev(end(lhs.data_)); // do not waste time for '\0'
const auto last2 = std::prev(end(rhs.data_));
for (; (first1 != last1) && (first2 != last2); ++first1, (void)++first2) {
if (*first1 < *first2) return true;
if (*first2 < *first1) return false;
} }
return first1 == last1 && first2 != last2;
}
template<std::size_t N2> #endif
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + N2> operator+(const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2>& rhs) noexcept
{
CharT txt[N + N2 + 1] = {};
for(size_t i = 0; i != N; ++i) template<class Traits>
txt[i] = lhs[i]; friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
for(size_t i = 0; i != N2; ++i) const basic_fixed_string& txt)
txt[N + i] = rhs[i]; {
return os << txt.c_str();
}
};
return units::basic_fixed_string(txt); template<typename CharT, std::size_t N>
} basic_fixed_string(const CharT (&str)[N]) -> basic_fixed_string<CharT, N - 1>;
};
template<typename CharT, std::size_t N> template<typename CharT>
basic_fixed_string(const CharT (&str)[N]) -> basic_fixed_string<CharT, N-1>; basic_fixed_string(CharT) -> basic_fixed_string<CharT, 1>;
template<typename CharT> template<std::size_t N>
basic_fixed_string(CharT) -> basic_fixed_string<CharT, 1>; using fixed_string = basic_fixed_string<char, N>;
template<std::size_t N> } // namespace units
using fixed_string = basic_fixed_string<char, N>;
}