Replace std::enable_if with requires
Introduce some concepts for enum and flags handling, goodbye and thanks for all the fish std::enable_if.
This commit is contained in:
parent
04f11c2af3
commit
fb4cef5b61
|
@ -30,8 +30,8 @@ public:
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
constexpr ArrayView(T(&array)[N]) : m_pointer(array), m_size(N) {}
|
constexpr ArrayView(T(&array)[N]) : m_pointer(array), m_size(N) {}
|
||||||
|
|
||||||
template<typename Container,
|
template<typename Container>
|
||||||
typename = std::enable_if_t<sizeof(decltype(*std::declval<Container>().data())) == sizeof(T)>>
|
requires (sizeof(decltype(*std::declval<Container>().data())) == sizeof(T))
|
||||||
constexpr ArrayView(Container&& c)
|
constexpr ArrayView(Container&& c)
|
||||||
: m_pointer(c.data()), m_size(c.size()) {}
|
: m_pointer(c.data()), m_size(c.size()) {}
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,8 @@ template<> struct PerArgumentCommandCompleter<>
|
||||||
template<typename Completer, typename... Rest>
|
template<typename Completer, typename... Rest>
|
||||||
struct PerArgumentCommandCompleter<Completer, Rest...> : PerArgumentCommandCompleter<Rest...>
|
struct PerArgumentCommandCompleter<Completer, Rest...> : PerArgumentCommandCompleter<Rest...>
|
||||||
{
|
{
|
||||||
template<typename C, typename... R,
|
template<typename C, typename... R>
|
||||||
typename = std::enable_if_t<not std::is_base_of<PerArgumentCommandCompleter<>,
|
requires (not std::is_base_of_v<PerArgumentCommandCompleter<>, std::remove_reference_t<C>>)
|
||||||
std::remove_reference_t<C>>::value>>
|
|
||||||
PerArgumentCommandCompleter(C&& completer, R&&... rest)
|
PerArgumentCommandCompleter(C&& completer, R&&... rest)
|
||||||
: PerArgumentCommandCompleter<Rest...>(std::forward<R>(rest)...),
|
: PerArgumentCommandCompleter<Rest...>(std::forward<R>(rest)...),
|
||||||
m_completer(std::forward<C>(completer)) {}
|
m_completer(std::forward<C>(completer)) {}
|
||||||
|
|
|
@ -2,12 +2,16 @@
|
||||||
#define enum_hh_INCLUDED
|
#define enum_hh_INCLUDED
|
||||||
|
|
||||||
#include "string.hh"
|
#include "string.hh"
|
||||||
|
#include "meta.hh"
|
||||||
|
|
||||||
namespace Kakoune
|
namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T> struct EnumDesc { T value; StringView name; };
|
template<typename T> struct EnumDesc { T value; StringView name; };
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept DescribedEnum = requires { enum_desc(Meta::Type<T>{}); };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // enum_hh_INCLUDED
|
#endif // enum_hh_INCLUDED
|
||||||
|
|
23
src/flags.hh
23
src/flags.hh
|
@ -11,22 +11,19 @@ namespace Kakoune
|
||||||
template<typename Flags>
|
template<typename Flags>
|
||||||
constexpr bool with_bit_ops(Meta::Type<Flags>) { return false; }
|
constexpr bool with_bit_ops(Meta::Type<Flags>) { return false; }
|
||||||
|
|
||||||
|
template<typename Flags>
|
||||||
|
concept WithBitOps = with_bit_ops(Meta::Type<Flags>{});
|
||||||
|
|
||||||
template<typename Flags>
|
template<typename Flags>
|
||||||
using UnderlyingType = std::underlying_type_t<Flags>;
|
using UnderlyingType = std::underlying_type_t<Flags>;
|
||||||
|
|
||||||
template<typename Flags, typename T = void>
|
template<WithBitOps Flags>
|
||||||
using EnableIfWithBitOps = std::enable_if_t<with_bit_ops(Meta::Type<Flags>{}), T>;
|
|
||||||
|
|
||||||
template<typename Flags, typename T = void>
|
|
||||||
using EnableIfWithoutBitOps = std::enable_if_t<not with_bit_ops(Meta::Type<Flags>{}), T>;
|
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
|
||||||
constexpr Flags operator|(Flags lhs, Flags rhs)
|
constexpr Flags operator|(Flags lhs, Flags rhs)
|
||||||
{
|
{
|
||||||
return (Flags)((UnderlyingType<Flags>) lhs | (UnderlyingType<Flags>) rhs);
|
return (Flags)((UnderlyingType<Flags>) lhs | (UnderlyingType<Flags>) rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<WithBitOps Flags>
|
||||||
constexpr Flags& operator|=(Flags& lhs, Flags rhs)
|
constexpr Flags& operator|=(Flags& lhs, Flags rhs)
|
||||||
{
|
{
|
||||||
(UnderlyingType<Flags>&) lhs |= (UnderlyingType<Flags>) rhs;
|
(UnderlyingType<Flags>&) lhs |= (UnderlyingType<Flags>) rhs;
|
||||||
|
@ -45,32 +42,32 @@ struct TestableFlags
|
||||||
constexpr bool operator!=(const TestableFlags<Flags>& other) const { return value != other.value; }
|
constexpr bool operator!=(const TestableFlags<Flags>& other) const { return value != other.value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<WithBitOps Flags>
|
||||||
constexpr TestableFlags<Flags> operator&(Flags lhs, Flags rhs)
|
constexpr TestableFlags<Flags> operator&(Flags lhs, Flags rhs)
|
||||||
{
|
{
|
||||||
return { (Flags)((UnderlyingType<Flags>) lhs & (UnderlyingType<Flags>) rhs) };
|
return { (Flags)((UnderlyingType<Flags>) lhs & (UnderlyingType<Flags>) rhs) };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<WithBitOps Flags>
|
||||||
constexpr Flags& operator&=(Flags& lhs, Flags rhs)
|
constexpr Flags& operator&=(Flags& lhs, Flags rhs)
|
||||||
{
|
{
|
||||||
(UnderlyingType<Flags>&) lhs &= (UnderlyingType<Flags>) rhs;
|
(UnderlyingType<Flags>&) lhs &= (UnderlyingType<Flags>) rhs;
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<WithBitOps Flags>
|
||||||
constexpr Flags operator~(Flags lhs)
|
constexpr Flags operator~(Flags lhs)
|
||||||
{
|
{
|
||||||
return (Flags)(~(UnderlyingType<Flags>)lhs);
|
return (Flags)(~(UnderlyingType<Flags>)lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<WithBitOps Flags>
|
||||||
constexpr Flags operator^(Flags lhs, Flags rhs)
|
constexpr Flags operator^(Flags lhs, Flags rhs)
|
||||||
{
|
{
|
||||||
return (Flags)((UnderlyingType<Flags>) lhs ^ (UnderlyingType<Flags>) rhs);
|
return (Flags)((UnderlyingType<Flags>) lhs ^ (UnderlyingType<Flags>) rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = EnableIfWithBitOps<Flags>>
|
template<WithBitOps Flags>
|
||||||
constexpr Flags& operator^=(Flags& lhs, Flags rhs)
|
constexpr Flags& operator^=(Flags& lhs, Flags rhs)
|
||||||
{
|
{
|
||||||
(UnderlyingType<Flags>&) lhs ^= (UnderlyingType<Flags>) rhs;
|
(UnderlyingType<Flags>&) lhs ^= (UnderlyingType<Flags>) rhs;
|
||||||
|
|
10
src/hash.hh
10
src/hash.hh
|
@ -11,16 +11,14 @@ namespace Kakoune
|
||||||
|
|
||||||
size_t hash_data(const char* data, size_t len);
|
size_t hash_data(const char* data, size_t len);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type> requires std::is_integral_v<Type>
|
||||||
std::enable_if_t<std::is_integral<Type>::value, size_t>
|
constexpr size_t hash_value(const Type& val)
|
||||||
constexpr hash_value(const Type& val)
|
|
||||||
{
|
{
|
||||||
return (size_t)val;
|
return (size_t)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type> requires std::is_enum_v<Type>
|
||||||
std::enable_if_t<std::is_enum<Type>::value, size_t>
|
constexpr size_t hash_value(const Type& val)
|
||||||
constexpr hash_value(const Type& val)
|
|
||||||
{
|
{
|
||||||
return hash_value((std::underlying_type_t<Type>)val);
|
return hash_value((std::underlying_type_t<Type>)val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,12 +182,7 @@ struct HashMap
|
||||||
return m_items.back().value;
|
return m_items.back().value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename KeyType>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
using EnableIfHashCompatible = std::enable_if_t<
|
|
||||||
IsHashCompatible<Key, std::decay_t<KeyType>>
|
|
||||||
>;
|
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
|
||||||
constexpr int find_index(const KeyType& key, size_t hash) const
|
constexpr int find_index(const KeyType& key, size_t hash) const
|
||||||
{
|
{
|
||||||
for (auto slot = m_index.compute_slot(hash); slot < m_index.size(); ++slot)
|
for (auto slot = m_index.compute_slot(hash); slot < m_index.size(); ++slot)
|
||||||
|
@ -201,13 +196,13 @@ struct HashMap
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr int find_index(const KeyType& key) const { return find_index(key, hash_value(key)); }
|
constexpr int find_index(const KeyType& key) const { return find_index(key, hash_value(key)); }
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr bool contains(const KeyType& key) const { return find_index(key) >= 0; }
|
constexpr bool contains(const KeyType& key) const { return find_index(key) >= 0; }
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, std::remove_cvref_t<KeyType>>
|
||||||
constexpr Value& operator[](KeyType&& key)
|
constexpr Value& operator[](KeyType&& key)
|
||||||
{
|
{
|
||||||
const auto hash = hash_value(key);
|
const auto hash = hash_value(key);
|
||||||
|
@ -221,7 +216,7 @@ struct HashMap
|
||||||
return m_items.back().value;
|
return m_items.back().value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr void remove(const KeyType& key)
|
constexpr void remove(const KeyType& key)
|
||||||
{
|
{
|
||||||
const auto hash = hash_value(key);
|
const auto hash = hash_value(key);
|
||||||
|
@ -234,7 +229,7 @@ struct HashMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr void unordered_remove(const KeyType& key)
|
constexpr void unordered_remove(const KeyType& key)
|
||||||
{
|
{
|
||||||
const auto hash = hash_value(key);
|
const auto hash = hash_value(key);
|
||||||
|
@ -249,10 +244,10 @@ struct HashMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr void erase(const KeyType& key) { unordered_remove(key); }
|
constexpr void erase(const KeyType& key) { unordered_remove(key); }
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr void remove_all(const KeyType& key)
|
constexpr void remove_all(const KeyType& key)
|
||||||
{
|
{
|
||||||
const auto hash = hash_value(key);
|
const auto hash = hash_value(key);
|
||||||
|
@ -275,14 +270,14 @@ struct HashMap
|
||||||
|
|
||||||
const Item& item(size_t index) const { return m_items[index]; }
|
const Item& item(size_t index) const { return m_items[index]; }
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr iterator find(const KeyType& key)
|
constexpr iterator find(const KeyType& key)
|
||||||
{
|
{
|
||||||
auto index = find_index(key);
|
auto index = find_index(key);
|
||||||
return index >= 0 ? begin() + index : end();
|
return index >= 0 ? begin() + index : end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename KeyType, typename = EnableIfHashCompatible<KeyType>>
|
template<typename KeyType> requires IsHashCompatible<Key, KeyType>
|
||||||
constexpr const_iterator find(const KeyType& key) const
|
constexpr const_iterator find(const KeyType& key) const
|
||||||
{
|
{
|
||||||
return const_cast<HashMap*>(this)->find(key);
|
return const_cast<HashMap*>(this)->find(key);
|
||||||
|
|
|
@ -19,8 +19,8 @@ namespace Kakoune
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_same<decltype(option_to_string(std::declval<T>())), String>::value, String>
|
String option_to_string(const T& value, Quoting)
|
||||||
option_to_string(const T& value, Quoting)
|
requires std::is_same_v<decltype(option_to_string(std::declval<T>())), String>
|
||||||
{
|
{
|
||||||
return option_to_string(value);
|
return option_to_string(value);
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,8 @@ constexpr decltype(T::option_type_name) option_type_name(Meta::Type<T>)
|
||||||
return T::option_type_name;
|
return T::option_type_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum>
|
template<typename Enum> requires std::is_enum_v<Enum>
|
||||||
std::enable_if_t<std::is_enum<Enum>::value, String>
|
String option_type_name(Meta::Type<Enum>)
|
||||||
option_type_name(Meta::Type<Enum>)
|
|
||||||
{
|
{
|
||||||
return format("{}({})", with_bit_ops(Meta::Type<Enum>{}) ? "flags" : "enum",
|
return format("{}({})", with_bit_ops(Meta::Type<Enum>{}) ? "flags" : "enum",
|
||||||
join(enum_desc(Meta::Type<Enum>{}) |
|
join(enum_desc(Meta::Type<Enum>{}) |
|
||||||
|
@ -256,8 +255,8 @@ inline String option_to_string(const StronglyTypedNumber<RealType, ValueType>& o
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Number>
|
template<typename Number>
|
||||||
std::enable_if_t<std::is_base_of<StronglyTypedNumber<Number, int>, Number>::value, Number>
|
requires std::is_base_of_v<StronglyTypedNumber<Number, int>, Number>
|
||||||
option_from_string(Meta::Type<Number>, StringView str)
|
Number option_from_string(Meta::Type<Number>, StringView str)
|
||||||
{
|
{
|
||||||
return Number{str_to_int(str)};
|
return Number{str_to_int(str)};
|
||||||
}
|
}
|
||||||
|
@ -290,8 +289,8 @@ inline void option_update(WorstMatch, const Context&)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Coord>
|
template<typename Coord>
|
||||||
std::enable_if_t<std::is_base_of<LineAndColumn<Coord, decltype(Coord::line), decltype(Coord::column)>, Coord>::value, Coord>
|
requires std::is_base_of_v<LineAndColumn<Coord, decltype(Coord::line), decltype(Coord::column)>, Coord>
|
||||||
option_from_string(Meta::Type<Coord>, StringView str)
|
Coord option_from_string(Meta::Type<Coord>, StringView str)
|
||||||
{
|
{
|
||||||
struct error : runtime_error { error(size_t) : runtime_error{"expected <line>,<column>"} {} };
|
struct error : runtime_error { error(size_t) : runtime_error{"expected <line>,<column>"} {} };
|
||||||
auto vals = str | split<StringView>(',')
|
auto vals = str | split<StringView>(',')
|
||||||
|
@ -305,8 +304,8 @@ inline String option_to_string(const LineAndColumn<EffectiveType, LineType, Colu
|
||||||
return format("{},{}", opt.line, opt.column);
|
return format("{},{}", opt.line, opt.column);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
template<DescribedEnum Flags> requires WithBitOps<Flags>
|
||||||
EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
|
String option_to_string(Flags flags)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||||
String res;
|
String res;
|
||||||
|
@ -321,8 +320,8 @@ EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
|
template<DescribedEnum Enum> requires (not WithBitOps<Enum>)
|
||||||
EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
String option_to_string(Enum e)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
||||||
auto it = find_if(desc, [e](const EnumDesc<Enum>& d) { return d.value == e; });
|
auto it = find_if(desc, [e](const EnumDesc<Enum>& d) { return d.value == e; });
|
||||||
|
@ -332,8 +331,8 @@ EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
template<DescribedEnum Flags> requires WithBitOps<Flags>
|
||||||
EnableIfWithBitOps<Flags, Flags> option_from_string(Meta::Type<Flags>, StringView str)
|
Flags option_from_string(Meta::Type<Flags>, StringView str)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
constexpr auto desc = enum_desc(Meta::Type<Flags>{});
|
||||||
Flags flags{};
|
Flags flags{};
|
||||||
|
@ -347,8 +346,8 @@ EnableIfWithBitOps<Flags, Flags> option_from_string(Meta::Type<Flags>, StringVie
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
|
template<DescribedEnum Enum> requires (not WithBitOps<Enum>)
|
||||||
EnableIfWithoutBitOps<Enum, Enum> option_from_string(Meta::Type<Enum>, StringView str)
|
Enum option_from_string(Meta::Type<Enum>, StringView str)
|
||||||
{
|
{
|
||||||
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
constexpr auto desc = enum_desc(Meta::Type<Enum>{});
|
||||||
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
|
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
|
||||||
|
@ -357,16 +356,16 @@ EnableIfWithoutBitOps<Enum, Enum> option_from_string(Meta::Type<Enum>, StringVie
|
||||||
return it->value;
|
return it->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
template<DescribedEnum Flags> requires WithBitOps<Flags>
|
||||||
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
|
bool option_add(Flags& opt, StringView str)
|
||||||
{
|
{
|
||||||
const Flags old = opt;
|
const Flags old = opt;
|
||||||
opt |= option_from_string(Meta::Type<Flags>{}, str);
|
opt |= option_from_string(Meta::Type<Flags>{}, str);
|
||||||
return opt != old;
|
return opt != old;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
|
template<DescribedEnum Flags> requires WithBitOps<Flags>
|
||||||
EnableIfWithBitOps<Flags, bool> option_remove(Flags& opt, StringView str)
|
bool option_remove(Flags& opt, StringView str)
|
||||||
{
|
{
|
||||||
const Flags old = opt;
|
const Flags old = opt;
|
||||||
opt &= ~option_from_string(Meta::Type<Flags>{}, str);
|
opt &= ~option_from_string(Meta::Type<Flags>{}, str);
|
||||||
|
|
|
@ -136,14 +136,12 @@ decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val)
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename T> constexpr bool is_string = std::is_convertible<T, StringView>::value;
|
template<typename T> requires std::is_convertible_v<T, StringView>
|
||||||
|
|
||||||
template<typename T, class = std::enable_if_t<not is_string<T>>>
|
|
||||||
decltype(auto) format_param(const T& val) { return to_string(val); }
|
|
||||||
|
|
||||||
template<typename T, class = std::enable_if_t<is_string<T>>>
|
|
||||||
StringView format_param(const T& val) { return val; }
|
StringView format_param(const T& val) { return val; }
|
||||||
|
|
||||||
|
template<typename T> requires (not std::is_convertible_v<T, StringView>)
|
||||||
|
decltype(auto) format_param(const T& val) { return to_string(val); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String format(StringView fmt, ArrayView<const StringView> params);
|
String format(StringView fmt, ArrayView<const StringView> params);
|
||||||
|
|
|
@ -109,12 +109,12 @@ public:
|
||||||
bool operator>= (const iterator& other) const noexcept { return m_it >= other.m_it; }
|
bool operator>= (const iterator& other) const noexcept { return m_it >= other.m_it; }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_same<T, BaseIt>::value or std::is_same<T, Sentinel>::value, bool>
|
requires std::is_same_v<T, BaseIt> or std::is_same_v<T, Sentinel>
|
||||||
operator==(const T& other) const noexcept { return m_it == other; }
|
bool operator==(const T& other) const noexcept { return m_it == other; }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::enable_if_t<std::is_same<T, BaseIt>::value or std::is_same<T, Sentinel>::value, bool>
|
requires std::is_same_v<T, BaseIt> or std::is_same_v<T, Sentinel>
|
||||||
operator!=(const T& other) const noexcept { return m_it != other; }
|
bool operator!=(const T& other) const noexcept { return m_it != other; }
|
||||||
|
|
||||||
bool operator< (const BaseIt& other) const noexcept { return m_it < other; }
|
bool operator< (const BaseIt& other) const noexcept { return m_it < other; }
|
||||||
bool operator<= (const BaseIt& other) const noexcept { return m_it <= other; }
|
bool operator<= (const BaseIt& other) const noexcept { return m_it <= other; }
|
||||||
|
|
|
@ -16,8 +16,7 @@ struct Value
|
||||||
{
|
{
|
||||||
Value() = default;
|
Value() = default;
|
||||||
|
|
||||||
template<typename T,
|
template<typename T> requires (not std::is_same_v<Value, T>)
|
||||||
typename = std::enable_if_t<not std::is_same<Value, T>::value>>
|
|
||||||
Value(T&& val)
|
Value(T&& val)
|
||||||
: m_value{new Model<std::decay_t<T>>{std::forward<T>(val)}} {}
|
: m_value{new Model<std::decay_t<T>>{std::forward<T>(val)}} {}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user