@ -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 >