diff options
| author | Maxime Coste <mawww@kakoune.org> | 2020-11-11 21:43:27 +1100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2021-11-21 09:44:56 +1100 |
| commit | fb4cef5b61639c507e6c5740cc5973d0d79ba673 (patch) | |
| tree | 751e533a39d9a51be6b8af9e4abe6af75df00e87 /src | |
| parent | 04f11c2af3e0ecdc78df9800d381b2fdc46af3b7 (diff) | |
Replace std::enable_if with requires
Introduce some concepts for enum and flags handling, goodbye and
thanks for all the fish std::enable_if.
Diffstat (limited to 'src')
| -rw-r--r-- | src/array_view.hh | 4 | ||||
| -rw-r--r-- | src/commands.cc | 5 | ||||
| -rw-r--r-- | src/enum.hh | 4 | ||||
| -rw-r--r-- | src/flags.hh | 23 | ||||
| -rw-r--r-- | src/hash.hh | 10 | ||||
| -rw-r--r-- | src/hash_map.hh | 25 | ||||
| -rw-r--r-- | src/option_types.hh | 41 | ||||
| -rw-r--r-- | src/string_utils.hh | 8 | ||||
| -rw-r--r-- | src/utf8_iterator.hh | 8 | ||||
| -rw-r--r-- | src/value.hh | 3 |
10 files changed, 60 insertions, 71 deletions
diff --git a/src/array_view.hh b/src/array_view.hh index 6a363656..982b436f 100644 --- a/src/array_view.hh +++ b/src/array_view.hh @@ -30,8 +30,8 @@ public: template<size_t N> constexpr ArrayView(T(&array)[N]) : m_pointer(array), m_size(N) {} - template<typename Container, - typename = std::enable_if_t<sizeof(decltype(*std::declval<Container>().data())) == sizeof(T)>> + template<typename Container> + requires (sizeof(decltype(*std::declval<Container>().data())) == sizeof(T)) constexpr ArrayView(Container&& c) : m_pointer(c.data()), m_size(c.size()) {} diff --git a/src/commands.cc b/src/commands.cc index fbf14e8e..b7e2195e 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -70,9 +70,8 @@ template<> struct PerArgumentCommandCompleter<> template<typename Completer, typename... Rest> struct PerArgumentCommandCompleter<Completer, Rest...> : PerArgumentCommandCompleter<Rest...> { - template<typename C, typename... R, - typename = std::enable_if_t<not std::is_base_of<PerArgumentCommandCompleter<>, - std::remove_reference_t<C>>::value>> + template<typename C, typename... R> + requires (not std::is_base_of_v<PerArgumentCommandCompleter<>, std::remove_reference_t<C>>) PerArgumentCommandCompleter(C&& completer, R&&... rest) : PerArgumentCommandCompleter<Rest...>(std::forward<R>(rest)...), m_completer(std::forward<C>(completer)) {} diff --git a/src/enum.hh b/src/enum.hh index 09e11ef0..bedfea6d 100644 --- a/src/enum.hh +++ b/src/enum.hh @@ -2,12 +2,16 @@ #define enum_hh_INCLUDED #include "string.hh" +#include "meta.hh" namespace Kakoune { template<typename T> struct EnumDesc { T value; StringView name; }; +template<typename T> +concept DescribedEnum = requires { enum_desc(Meta::Type<T>{}); }; + } #endif // enum_hh_INCLUDED diff --git a/src/flags.hh b/src/flags.hh index 6b701016..6d4764f3 100644 --- a/src/flags.hh +++ b/src/flags.hh @@ -12,21 +12,18 @@ template<typename Flags> constexpr bool with_bit_ops(Meta::Type<Flags>) { return false; } template<typename Flags> -using UnderlyingType = std::underlying_type_t<Flags>; - -template<typename Flags, typename T = void> -using EnableIfWithBitOps = std::enable_if_t<with_bit_ops(Meta::Type<Flags>{}), T>; +concept WithBitOps = with_bit_ops(Meta::Type<Flags>{}); -template<typename Flags, typename T = void> -using EnableIfWithoutBitOps = std::enable_if_t<not with_bit_ops(Meta::Type<Flags>{}), T>; +template<typename Flags> +using UnderlyingType = std::underlying_type_t<Flags>; -template<typename Flags, typename = EnableIfWithBitOps<Flags>> +template<WithBitOps Flags> constexpr Flags operator|(Flags lhs, 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) { (UnderlyingType<Flags>&) lhs |= (UnderlyingType<Flags>) rhs; @@ -45,32 +42,32 @@ struct TestableFlags 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) { return { (Flags)((UnderlyingType<Flags>) lhs & (UnderlyingType<Flags>) rhs) }; } -template<typename Flags, typename = EnableIfWithBitOps<Flags>> +template<WithBitOps Flags> constexpr Flags& operator&=(Flags& lhs, Flags rhs) { (UnderlyingType<Flags>&) lhs &= (UnderlyingType<Flags>) rhs; return lhs; } -template<typename Flags, typename = EnableIfWithBitOps<Flags>> +template<WithBitOps Flags> constexpr Flags operator~(Flags lhs) { return (Flags)(~(UnderlyingType<Flags>)lhs); } -template<typename Flags, typename = EnableIfWithBitOps<Flags>> +template<WithBitOps Flags> constexpr Flags operator^(Flags lhs, 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) { (UnderlyingType<Flags>&) lhs ^= (UnderlyingType<Flags>) rhs; diff --git a/src/hash.hh b/src/hash.hh index 23ae50a9..8dcd719f 100644 --- a/src/hash.hh +++ b/src/hash.hh @@ -11,16 +11,14 @@ namespace Kakoune size_t hash_data(const char* data, size_t len); -template<typename Type> -std::enable_if_t<std::is_integral<Type>::value, size_t> -constexpr hash_value(const Type& val) +template<typename Type> requires std::is_integral_v<Type> +constexpr size_t hash_value(const Type& val) { return (size_t)val; } -template<typename Type> -std::enable_if_t<std::is_enum<Type>::value, size_t> -constexpr hash_value(const Type& val) +template<typename Type> requires std::is_enum_v<Type> +constexpr size_t hash_value(const Type& val) { return hash_value((std::underlying_type_t<Type>)val); } diff --git a/src/hash_map.hh b/src/hash_map.hh index b5f054bc..b7ae4494 100644 --- a/src/hash_map.hh +++ b/src/hash_map.hh @@ -182,12 +182,7 @@ struct HashMap return m_items.back().value; } - template<typename KeyType> - using EnableIfHashCompatible = std::enable_if_t< - IsHashCompatible<Key, std::decay_t<KeyType>> - >; - - template<typename KeyType, typename = EnableIfHashCompatible<KeyType>> + template<typename KeyType> requires IsHashCompatible<Key, KeyType> constexpr int find_index(const KeyType& key, size_t hash) const { for (auto slot = m_index.compute_slot(hash); slot < m_index.size(); ++slot) @@ -201,13 +196,13 @@ struct HashMap 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)); } - 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; } - template<typename KeyType, typename = EnableIfHashCompatible<KeyType>> + template<typename KeyType> requires IsHashCompatible<Key, std::remove_cvref_t<KeyType>> constexpr Value& operator[](KeyType&& key) { const auto hash = hash_value(key); @@ -221,7 +216,7 @@ struct HashMap return m_items.back().value; } - template<typename KeyType, typename = EnableIfHashCompatible<KeyType>> + template<typename KeyType> requires IsHashCompatible<Key, KeyType> constexpr void remove(const KeyType& 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) { 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); } - template<typename KeyType, typename = EnableIfHashCompatible<KeyType>> + template<typename KeyType> requires IsHashCompatible<Key, KeyType> constexpr void remove_all(const KeyType& key) { const auto hash = hash_value(key); @@ -275,14 +270,14 @@ struct HashMap 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) { auto index = find_index(key); 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 { return const_cast<HashMap*>(this)->find(key); diff --git a/src/option_types.hh b/src/option_types.hh index e576b295..40d367df 100644 --- a/src/option_types.hh +++ b/src/option_types.hh @@ -19,8 +19,8 @@ namespace Kakoune { template<typename T> -std::enable_if_t<std::is_same<decltype(option_to_string(std::declval<T>())), String>::value, String> -option_to_string(const T& value, Quoting) +String 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); } @@ -31,9 +31,8 @@ constexpr decltype(T::option_type_name) option_type_name(Meta::Type<T>) return T::option_type_name; } -template<typename Enum> -std::enable_if_t<std::is_enum<Enum>::value, String> -option_type_name(Meta::Type<Enum>) +template<typename Enum> requires std::is_enum_v<Enum> +String option_type_name(Meta::Type<Enum>) { return format("{}({})", with_bit_ops(Meta::Type<Enum>{}) ? "flags" : "enum", join(enum_desc(Meta::Type<Enum>{}) | @@ -256,8 +255,8 @@ inline String option_to_string(const StronglyTypedNumber<RealType, ValueType>& o } template<typename Number> -std::enable_if_t<std::is_base_of<StronglyTypedNumber<Number, int>, Number>::value, Number> -option_from_string(Meta::Type<Number>, StringView str) + requires std::is_base_of_v<StronglyTypedNumber<Number, int>, Number> +Number option_from_string(Meta::Type<Number>, StringView str) { return Number{str_to_int(str)}; } @@ -290,8 +289,8 @@ inline void option_update(WorstMatch, const Context&) } template<typename Coord> -std::enable_if_t<std::is_base_of<LineAndColumn<Coord, decltype(Coord::line), decltype(Coord::column)>, Coord>::value, Coord> -option_from_string(Meta::Type<Coord>, StringView str) + requires std::is_base_of_v<LineAndColumn<Coord, decltype(Coord::line), decltype(Coord::column)>, Coord> +Coord option_from_string(Meta::Type<Coord>, StringView str) { struct error : runtime_error { error(size_t) : runtime_error{"expected <line>,<column>"} {} }; 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); } -template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))> -EnableIfWithBitOps<Flags, String> option_to_string(Flags flags) +template<DescribedEnum Flags> requires WithBitOps<Flags> +String option_to_string(Flags flags) { constexpr auto desc = enum_desc(Meta::Type<Flags>{}); String res; @@ -321,8 +320,8 @@ EnableIfWithBitOps<Flags, String> option_to_string(Flags flags) return res; } -template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))> -EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e) +template<DescribedEnum Enum> requires (not WithBitOps<Enum>) +String option_to_string(Enum e) { constexpr auto desc = enum_desc(Meta::Type<Enum>{}); 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 {}; } -template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))> -EnableIfWithBitOps<Flags, Flags> option_from_string(Meta::Type<Flags>, StringView str) +template<DescribedEnum Flags> requires WithBitOps<Flags> +Flags option_from_string(Meta::Type<Flags>, StringView str) { constexpr auto desc = enum_desc(Meta::Type<Flags>{}); Flags flags{}; @@ -347,8 +346,8 @@ EnableIfWithBitOps<Flags, Flags> option_from_string(Meta::Type<Flags>, StringVie return flags; } -template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))> -EnableIfWithoutBitOps<Enum, Enum> option_from_string(Meta::Type<Enum>, StringView str) +template<DescribedEnum Enum> requires (not WithBitOps<Enum>) +Enum option_from_string(Meta::Type<Enum>, StringView str) { constexpr auto desc = enum_desc(Meta::Type<Enum>{}); 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; } -template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))> -EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str) +template<DescribedEnum Flags> requires WithBitOps<Flags> +bool option_add(Flags& opt, StringView str) { const Flags old = opt; opt |= option_from_string(Meta::Type<Flags>{}, str); return opt != old; } -template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))> -EnableIfWithBitOps<Flags, bool> option_remove(Flags& opt, StringView str) +template<DescribedEnum Flags> requires WithBitOps<Flags> +bool option_remove(Flags& opt, StringView str) { const Flags old = opt; opt &= ~option_from_string(Meta::Type<Flags>{}, str); diff --git a/src/string_utils.hh b/src/string_utils.hh index e0adc181..a11aaa91 100644 --- a/src/string_utils.hh +++ b/src/string_utils.hh @@ -136,14 +136,12 @@ decltype(auto) to_string(const StronglyTypedNumber<RealType, ValueType>& val) 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> +StringView format_param(const T& val) { return val; } -template<typename T, class = std::enable_if_t<not is_string<T>>> +template<typename T> requires (not std::is_convertible_v<T, StringView>) 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; } - } String format(StringView fmt, ArrayView<const StringView> params); diff --git a/src/utf8_iterator.hh b/src/utf8_iterator.hh index 81302ef9..618a44a9 100644 --- a/src/utf8_iterator.hh +++ b/src/utf8_iterator.hh @@ -109,12 +109,12 @@ public: bool operator>= (const iterator& other) const noexcept { return m_it >= other.m_it; } template<typename T> - std::enable_if_t<std::is_same<T, BaseIt>::value or std::is_same<T, Sentinel>::value, bool> - operator==(const T& other) const noexcept { return m_it == other; } + requires std::is_same_v<T, BaseIt> or std::is_same_v<T, Sentinel> + bool operator==(const T& other) const noexcept { return m_it == other; } template<typename T> - std::enable_if_t<std::is_same<T, BaseIt>::value or std::is_same<T, Sentinel>::value, bool> - operator!=(const T& other) const noexcept { return m_it != other; } + requires std::is_same_v<T, BaseIt> or std::is_same_v<T, Sentinel> + 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; } diff --git a/src/value.hh b/src/value.hh index 51394c7d..aa53afb8 100644 --- a/src/value.hh +++ b/src/value.hh @@ -16,8 +16,7 @@ struct Value { Value() = default; - template<typename T, - typename = std::enable_if_t<not std::is_same<Value, T>::value>> + template<typename T> requires (not std::is_same_v<Value, T>) Value(T&& val) : m_value{new Model<std::decay_t<T>>{std::forward<T>(val)}} {} |
