Added array literal initialisers for `string_ord<char[N]>`.

Fortune for libexopt's current commit: Half curse − 半凶
boxed_is_boxed_value
Avril 1 year ago
parent 7ce1fd2ad0
commit ea8121058f
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -4,7 +4,7 @@
#include "exopt.h"
#ifdef __cplusplus
//#include "util.hh"
#include "util.hh"
#include <string_view>
#include <concepts>
@ -88,8 +88,17 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
if constexpr(!N) return M;
else if constexpr(!M) return N;
//else if constexpr(M < N) return N - M; // These lines are not correct, just fixing the sizes does not make the edit valid
//else if constexpr(N < M) return M - N; // ^
else if constexpr(M < N) return N - M;
else if constexpr(N < M) return M - N;
else return leven_diff<N>(std::string_view{sa}, std::string_view{sb});
}
template<size_t M, size_t N>
constexpr decltype(auto) leven_diff(std::array<char, M> const& sa, std::array<char, N> const& sb) noexcept {
if constexpr(!N) return M;
else if constexpr(!M) return N;
else if constexpr(M < N) return N - M;
else if constexpr(N < M) return M - N;
else return leven_diff<N>(std::string_view{sa}, std::string_view{sb});
}
@ -100,9 +109,19 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
struct string_ord {
using string_type = std::remove_reference_t<S>;
constexpr string_ord(string_type&& str) noexcept
template<typename... Args> requires(std::is_constructible_v<string_type, Args...>)
constexpr string_ord(Args&&... args) noexcept(std::is_nothrow_constructible_v<string_type, Args...>)
: m_string{std::forward<Args>(args)...} {}
// { return { S(std::forward<Args>(args)...) }; }
constexpr string_ord(std::add_rvalue_reference_t<S> str) noexcept requires(!std::is_array_v<string_type>)
: m_string(std::move(str)) {}
constexpr string_ord(const char (&str)[sizeof(string_type)]) requires(std::is_array_v<string_type>)
: string_ord(std::move(str), std::make_index_sequence<sizeof(string_type)>{}) {}
constexpr string_ord(const char (&&str)[sizeof(string_type)]) requires(std::is_array_v<string_type>)
: string_ord(std::move(str), std::make_index_sequence<sizeof(string_type)>{}) {}
constexpr string_ord(string_ord const&) = default;
constexpr string_ord(string_ord &&) = default;
constexpr string_ord& operator=(string_ord const&) = default;
@ -121,7 +140,17 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
return ab <=> ba;
}
constexpr operator std::string_view() const noexcept { return m_string; }
constexpr std::string_view view() const noexcept { if constexpr(std::is_array_v<string_type>) return { m_string, sizeof(string_type) - 1 }; else return { m_string }; }
constexpr operator std::string_view() const noexcept { return view(); }
template<typename U> requires(std::is_convertible_v<U, std::string_view> and std::is_convertible_v<string_type&&, U>)
constexpr explicit operator string_ord<U>() && noexcept { return { std::move(m_string) }; }
template<typename U> requires(std::is_convertible_v<U, std::string_view> and std::is_convertible_v<string_type&&, U> and std::is_constructible_v<U, string_type const&&>)
constexpr explicit operator string_ord<U>() const&& noexcept { return { U{std::move(m_string)} }; }
template<typename U> requires(std::is_convertible_v<U, std::string_view> and std::is_convertible_v<string_type&&, U> and std::is_constructible_v<U, string_type const&>)
constexpr explicit operator string_ord<U>() const& noexcept { return { U{m_string} }; }
constexpr string_type& string() noexcept { return m_string; }
constexpr string_type const& string() const noexcept { return m_string; }
@ -133,8 +162,14 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
constexpr string_type const&& operator*() const&& noexcept { return std::move(m_string); }
private:
template<size_t... Is> requires(sizeof...(Is) == sizeof(string_type))
constexpr string_ord(const char (&&l)[sizeof(string_type)], std::index_sequence<Is...>) noexcept requires(std::is_array_v<string_type>)
: m_string { l[Is]... } {}
string_type m_string;
};
template<size_t N>
string_ord(const char (&l)[N]) -> string_ord<decltype(l)>;
/// Used to store all valid command names, so when an invalid one is found, the closest matching one(s) can be suggested to the user in a "did you mean ..." format with the *lowest difference* neighbour(s) to the invalid string first.
template<typename T, std::convertible_to<std::string_view> S = std::string_view>

@ -2,6 +2,7 @@
#include <string_view>
#include <utility>
#include <array>
#include "exopt.h"
@ -34,4 +35,22 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
static_assert(comptime_value(std::string_view{"hello"}.size()) == 5, "Bad comptime_value()");
static_assert(_EO_CONSTANT_VALUE(std::string_view{"hello world"}) == std::string_view{"hello world"}, "Bad CONSTANT_VALUE()");
template<typename T, size_t N, typename Array= T[N], typename _I = std::make_index_sequence<N>>
constexpr decltype(auto) array_literal(const T (&a)[N]) noexcept {
constexpr decltype(auto) _array_create = []<size_t... I>(auto const& a, std::index_sequence<I...>) noexcept
{
return Array { a[I]... };
};
return _array_create(std::move(a), _I{});
}
template<typename T, size_t N, typename Array= T[N], typename _I = std::make_index_sequence<N>>
constexpr decltype(auto) array_literal(T (&&a)[N]) noexcept {
constexpr decltype(auto) _array_create = []<size_t... I>(auto&& a, std::index_sequence<I...>) noexcept
{
return Array { std::move(a[I])... };
};
return _array_create(std::move(a), _I{});
}
} }

@ -17,7 +17,14 @@ extern "C" {
}
namespace exopt {
namespace util [[gnu::visibility("internal")]] {
namespace util [[gnu::visibility("internal")]] {
namespace {
constexpr string_ord a("hello world");
constexpr string_ord b{""};
static_assert(a.view()[a.view().size()-1], "Levenshtein distance size mismatch for array literals");
static_assert(b.view().empty(), "Levenshtein distance size mismatch for array literals (empty)");
static_assert(a.difference_from(b) == (sizeof(a) - sizeof(b)), "Levenshtein distance size mismatch for array literals (calculation)");
}
static_assert(leven_diff("hello world", "Hello World") == 2, "Levelshtein distance incorrect for non-matching strings");
static_assert(leven_diff("hello world", "hello world") == 0, "Levelshtein distance incorrect for matching strings");
static_assert(leven_diff("hello world", std::string_view{"hello world"}) == 0, "Levelshtein distance incorrect for matching string container type 1");

Loading…
Cancel
Save