summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2020-11-11 21:43:27 +1100
committerMaxime Coste <mawww@kakoune.org>2021-11-21 09:44:56 +1100
commitfb4cef5b61639c507e6c5740cc5973d0d79ba673 (patch)
tree751e533a39d9a51be6b8af9e4abe6af75df00e87 /src
parent04f11c2af3e0ecdc78df9800d381b2fdc46af3b7 (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.hh4
-rw-r--r--src/commands.cc5
-rw-r--r--src/enum.hh4
-rw-r--r--src/flags.hh23
-rw-r--r--src/hash.hh10
-rw-r--r--src/hash_map.hh25
-rw-r--r--src/option_types.hh41
-rw-r--r--src/string_utils.hh8
-rw-r--r--src/utf8_iterator.hh8
-rw-r--r--src/value.hh3
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)}} {}