Fixed spooky "confused" compiler fatal error (w/ no error messages) in `make_ordered_strign()`.

Fortune for libexopt's current commit: Future blessing − 末吉
boxed_is_boxed_value
Avril 1 year ago
parent 7447615b48
commit d4c494c6c1
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,6 +1,49 @@
#pragma once
namespace exopt::types {
#if 0
//XXX: Eh, this trait design is NOT GOOD. Figure out a better one
namespace traits {
template<typename T>
struct impl_clone {
typedef T type;
constexpr static T clone(T const& v) const noexcept(std::is_nothrow_copy_constructible_v<type>) { return v; }
};
template<>
struct impl_clone<void> {};
template<typename> struct clone;
template<>
struct clone : impl_clone<void> {};
template<typename T>
struct clone : impl_clone<std::conditional_t< std::is_copy_constructible_v<T>, T, void> > {};
template<typename T>
struct clone : impl_clone<std::conditional_t
< requires(requires(T const& self) {
{ self.clone() } noexcept(std::is_nothrow_copy_constructible_v<T>)
-> std::same_as<T>;
})
, T
, void
> > {
constexpr static T clone(T const&
};
}
template<typename T>
concept Clone = requires(T const& self) {
typename traits::clone<T>::type;
{ traits::clone<T>::clone(self) } noexcept(std::is_nothrow_copy_constructible_v<T>) -> std::same_as<T>;
} or requires(T const& self) {
{ self.clone() } noexcept(std::is_nothrow_copy_constructible_v<T>) -> std::same_as<T>;
};
#endif
namespace either [[gnu::visibility("internal")]] {
//TODO: A version with std::shared_ptr<T> instead
template<typename T>//, typename P = T*>
@ -178,5 +221,5 @@ namespace exopt::types {
/// RC-lifetime managed Cow<T>
template<typename T>
using AutoCow = Cow<std::shared_ptr<T>>;
using RcCow = Cow<std::shared_ptr<T>>;
}

@ -11,6 +11,7 @@
#include <vector>
#include <map>
#include <array>
#include <memory>
#include <span>
#include <tuple>
@ -134,12 +135,17 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
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>)
constexpr string_ord(const char (&str)[sizeof(string_type)]) noexcept 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>)
constexpr string_ord(const char (&&str)[sizeof(string_type)]) noexcept requires(std::is_array_v<string_type>)
: string_ord(std::move(str), std::make_index_sequence<sizeof(string_type)>{}) {}
constexpr static string_ord from_char_array(std::array<char, sizeof(string_type)>&& l) noexcept requires(std::is_array_v<string_type>)
{
return { std::move(l) };
}
constexpr string_ord(string_ord const&) = default;
constexpr string_ord(string_ord &&) = default;
constexpr string_ord& operator=(string_ord const&) = default;
@ -190,6 +196,7 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
if constexpr(std::is_array_v<string_type>) {
struct OS : public OrderedString {
std::array<char, sizeof(string_type)> str;
constexpr static bool is_array() noexcept { return true; }
constexpr virtual ~OS() = default;
constexpr OS(string_type const& str) noexcept : OrderedString(), str(util::array_literal(std::forward<decltype(str)>(str))) {}
@ -207,6 +214,7 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
} else {
struct OS : public OrderedString {
string_type str;
constexpr static bool is_array() noexcept { return false; }
constexpr virtual ~OS() = default;
constexpr OS(string_type&& str) noexcept : OrderedString(), str(std::move(str)) {}
@ -227,6 +235,10 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
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]... } {}
template<size_t... Is> requires(sizeof...(Is) == sizeof(string_type))
constexpr explicit string_ord(std::array<char, sizeof(string_type)>&& l, std::index_sequence<Is...>) noexcept requires(std::is_array_v<string_type>)
: m_string { l[Is]... } {}
string_type m_string;
};
template<size_t N>
@ -234,6 +246,72 @@ namespace exopt { namespace util [[gnu::visibility("internal")]] {
template<typename T>
string_ord(T&&) -> string_ord<T>;
/// Create a dynamic instance of `string_ord<T>`.
/// This should be passed immediately to a call to `std::make_{unique/shared}` for most cases
template<typename T, typename... Args> requires(std::is_convertible_v<T, std::string_view> and std::is_constructible_v<T, Args...>)
constexpr decltype(auto) make_dynamic_ordered_string(Args&&... ctor) noexcept(std::is_nothrow_constructible_v<T, Args...>)
{
using str = string_ord<T>;
return str{ std::forward<Args>(ctor)... }.make_dynamic();
}
template<std::convertible_to<std::string_view> T>
constexpr decltype(auto) make_dynamic_ordered_string(T&& value) noexcept(std::is_nothrow_move_constructible_v<T>)
{
return string_ord<T>{ std::move(value) }.make_dynamic();
}
template<std::convertible_to<std::string_view> T>
constexpr auto make_unique_ordered_string(T&& value) noexcept(std::is_nothrow_move_constructible_v<T>)
{
auto&& tmp = make_dynamic_ordered_string<T>(std::move(value));
return std::make_unique<std::remove_reference_t<decltype(tmp)>>(std::move(tmp));
}
template<std::convertible_to<std::string_view> T>
constexpr auto make_shared_ordered_string(T&& value) noexcept(std::is_nothrow_move_constructible_v<T>)
{
auto&& tmp = make_dynamic_ordered_string<T>(std::move(value));
return std::make_shared<std::remove_reference_t<decltype(tmp)>>(std::move(tmp));
}
template<typename T, typename... Args> requires(std::is_convertible_v<T, std::string_view> and std::is_constructible_v<T, Args...>)
constexpr auto make_ordered_string(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
{
auto dyn = make_dynamic_ordered_string<T, Args...>(std::forward<Args>(args)...);
struct mover {
using type = std::remove_reference_t<decltype(dyn)>;
using string_type = decltype(dyn.str);
type value;
/* constexpr explicit operator auto() noexcept {
if constexpr(type::is_array())
return string_ord<string_type>::from_char_array(std::move(value.str));
else return string_ord<string_type>{ std::move(value.str) };
}*/
constexpr operator std::shared_ptr<type>() noexcept { return std::make_shared<type>(std::move(value)); }
constexpr operator std::unique_ptr<type>() && noexcept { return std::make_unique<type>(std::move(value)); }
constexpr std::unique_ptr<type> unique() && noexcept { return std::make_unique<type>(std::move(value)); }
constexpr std::shared_ptr<type> shared() noexcept { return this-> operator std::shared_ptr<type>(); }
constexpr ~mover() = default;
/*
constexpr string_type const&& exposed() const&& noexcept requires(!type::is_array()){ return std::move(value.str); }
constexpr string_type const& exposed() const& noexcept requires(!type::is_array()){ return value.str; }
constexpr string_type&& exposed() && noexcept requires(!type::is_array()) { return std::move(value.str); }
constexpr string_type exposed() & noexcept requires(!type::is_array()){ return value.str; }
//constexpr string_type const& exposed() const noexcept { return value.str; }
constexpr explicit operator type&&() && noexcept { return std::move(value); }
constexpr explicit operator string_type&&() && noexcept requires(!type::is_array()) { return std::move(value.str); }
constexpr explicit operator std::string_view() const noexcept { return { value }; }*/
};
return mover{std::move(dyn)};
}
/// 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>
using sim_map = std::map<string_ord<S>, T>;

@ -22,6 +22,11 @@ namespace exopt {
constexpr string_ord a("hello world");
constexpr string_ord c{a.view()};
constexpr string_ord b{""};
consteval bool check_dynamic() noexcept {
auto d = make_ordered_string<decltype("hello")>("hello").unique();
return d->size() == (sizeof("hello") -1);
}
static_assert(check_dynamic(), "Levenshtein: Bad dynamic sizing");
static_assert(a.view()[a.view().size()-1], "Levenshtein distance size mismatch for array literals");
static_assert(a.difference_from(c) == 0, "Levenshtein distance mismatch when converting from array literal");
static_assert(a.make_dynamic().view() == c.make_dynamic(), "Levenshtein distance mismatch when converting from array literal to dynamic");

Loading…
Cancel
Save