summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2017-03-15 17:42:02 +0000
committerMaxime Coste <mawww@kakoune.org>2017-03-15 17:42:02 +0000
commita49e175727928b8b45c0c2ccdb01f143ea6d18c2 (patch)
tree88c1c3909c2ab06394a63af5ebab8fdcd0a389f0
parenta88e58763bd33e021511d2e821703f478afd85bf (diff)
Migrate to a more value based meta programming model
Introduce Meta::Type<T> to store a type as value, and pass it around, migrate enum_desc and option_type_name to this.
-rw-r--r--src/buffer.hh4
-rw-r--r--src/client.hh2
-rw-r--r--src/commands.cc14
-rw-r--r--src/enum.hh19
-rw-r--r--src/input_handler.hh2
-rw-r--r--src/insert_completer.hh12
-rw-r--r--src/meta.hh14
-rw-r--r--src/option_manager.hh4
-rw-r--r--src/option_types.hh44
9 files changed, 62 insertions, 53 deletions
diff --git a/src/buffer.hh b/src/buffer.hh
index 81f68441..bc960b20 100644
--- a/src/buffer.hh
+++ b/src/buffer.hh
@@ -21,7 +21,7 @@ enum class EolFormat
Crlf
};
-constexpr Array<EnumDesc<EolFormat>, 2> enum_desc(EolFormat)
+constexpr Array<EnumDesc<EolFormat>, 2> enum_desc(Meta::Type<EolFormat>)
{
return { {
{ EolFormat::Lf, "lf" },
@@ -35,7 +35,7 @@ enum class ByteOrderMark
Utf8
};
-constexpr Array<EnumDesc<ByteOrderMark>, 2> enum_desc(ByteOrderMark)
+constexpr Array<EnumDesc<ByteOrderMark>, 2> enum_desc(Meta::Type<ByteOrderMark>)
{
return { {
{ ByteOrderMark::None, "none" },
diff --git a/src/client.hh b/src/client.hh
index 80a1ef08..d5abc929 100644
--- a/src/client.hh
+++ b/src/client.hh
@@ -131,7 +131,7 @@ enum class Autoreload
Ask
};
-constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Autoreload)
+constexpr Array<EnumDesc<Autoreload>, 5> enum_desc(Meta::Type<Autoreload>)
{
return { {
{ Autoreload::Yes, "yes" },
diff --git a/src/commands.cc b/src/commands.cc
index 7ffc0c0e..a57e8031 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -43,17 +43,15 @@
namespace Kakoune
{
-template<>
-struct option_type_name<TimestampedList<LineAndFlag>>
+StringView option_type_name(Meta::Type<TimestampedList<LineAndFlag>>)
{
- static StringView name() { return "line-flags"; }
-};
+ return "line-flags";
+}
-template<>
-struct option_type_name<TimestampedList<RangeAndFace>>
+StringView option_type_name(Meta::Type<TimestampedList<RangeAndFace>>)
{
- static StringView name() { return "range-faces"; }
-};
+ return "range-faces";
+}
namespace
{
diff --git a/src/enum.hh b/src/enum.hh
index 01f89b32..56242508 100644
--- a/src/enum.hh
+++ b/src/enum.hh
@@ -5,6 +5,7 @@
#include "string.hh"
#include "exception.hh"
#include "containers.hh"
+#include "meta.hh"
namespace Kakoune
{
@@ -22,10 +23,10 @@ struct Array
template<typename T> struct EnumDesc { T value; StringView name; };
-template<typename Flags, typename = decltype(enum_desc(Flags{}))>
+template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
{
- constexpr auto desc = enum_desc(Flags{});
+ constexpr auto desc = enum_desc(Meta::Type<Flags>{});
String res;
for (int i = 0; i < desc.size(); ++i)
{
@@ -38,10 +39,10 @@ EnableIfWithBitOps<Flags, String> option_to_string(Flags flags)
return res;
}
-template<typename Enum, typename = decltype(enum_desc(Enum{}))>
+template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
{
- constexpr auto desc = enum_desc(Enum{});
+ constexpr auto desc = enum_desc(Meta::Type<Enum>{});
auto it = find_if(desc, [e](const EnumDesc<Enum>& d) { return d.value == e; });
if (it != desc.end())
return it->name.str();
@@ -49,10 +50,10 @@ EnableIfWithoutBitOps<Enum, String> option_to_string(Enum e)
return {};
}
-template<typename Flags, typename = decltype(enum_desc(Flags{}))>
+template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
{
- constexpr auto desc = enum_desc(Flags{});
+ constexpr auto desc = enum_desc(Meta::Type<Flags>{});
flags = Flags{};
for (auto s : str | split<StringView>('|'))
{
@@ -63,17 +64,17 @@ EnableIfWithBitOps<Flags> option_from_string(StringView str, Flags& flags)
}
}
-template<typename Enum, typename = decltype(enum_desc(Enum{}))>
+template<typename Enum, typename = decltype(enum_desc(Meta::Type<Enum>{}))>
EnableIfWithoutBitOps<Enum> option_from_string(StringView str, Enum& e)
{
- constexpr auto desc = enum_desc(Enum{});
+ constexpr auto desc = enum_desc(Meta::Type<Enum>{});
auto it = find_if(desc, [str](const EnumDesc<Enum>& d) { return d.name == str; });
if (it == desc.end())
throw runtime_error(format("invalid enum value '{}'", str));
e = it->value;
}
-template<typename Flags, typename = decltype(enum_desc(Flags{}))>
+template<typename Flags, typename = decltype(enum_desc(Meta::Type<Flags>{}))>
EnableIfWithBitOps<Flags, bool> option_add(Flags& opt, StringView str)
{
Flags res = Flags{};
diff --git a/src/input_handler.hh b/src/input_handler.hh
index 43fd9ecb..fd13a5a0 100644
--- a/src/input_handler.hh
+++ b/src/input_handler.hh
@@ -134,7 +134,7 @@ enum class AutoInfo
template<>
struct WithBitOps<AutoInfo> : std::true_type {};
-constexpr Array<EnumDesc<AutoInfo>, 3> enum_desc(AutoInfo)
+constexpr Array<EnumDesc<AutoInfo>, 3> enum_desc(Meta::Type<AutoInfo>)
{
return { {
{ AutoInfo::Command, "command"},
diff --git a/src/insert_completer.hh b/src/insert_completer.hh
index dac3db27..d7061c37 100644
--- a/src/insert_completer.hh
+++ b/src/insert_completer.hh
@@ -37,18 +37,18 @@ using InsertCompleterDescList = Vector<InsertCompleterDesc, MemoryDomain::Option
String option_to_string(const InsertCompleterDesc& opt);
void option_from_string(StringView str, InsertCompleterDesc& opt);
-template<> struct option_type_name<InsertCompleterDesc>
+inline StringView option_type_name(Meta::Type<InsertCompleterDesc>)
{
- static constexpr StringView name() { return "completer"; }
-};
+ return "completer";
+}
using CompletionCandidate = std::tuple<String, String, String>;
using CompletionList = PrefixedList<String, CompletionCandidate>;
-template<> struct option_type_name<CompletionList>
+inline StringView option_type_name(Meta::Type<CompletionList>)
{
- static constexpr StringView name() { return "completions"; }
-};
+ return "completions";
+}
struct InsertCompletion
{
diff --git a/src/meta.hh b/src/meta.hh
new file mode 100644
index 00000000..32f28dbb
--- /dev/null
+++ b/src/meta.hh
@@ -0,0 +1,14 @@
+#ifndef meta_hh_INCLUDED
+#define meta_hh_INCLUDED
+
+namespace Kakoune
+{
+namespace Meta
+{
+
+template<typename T> struct Type {};
+
+}
+}
+
+#endif // meta_hh_INCLUDED
diff --git a/src/option_manager.hh b/src/option_manager.hh
index 958a01f4..e794a3c9 100644
--- a/src/option_manager.hh
+++ b/src/option_manager.hh
@@ -221,8 +221,8 @@ public:
return **it;
throw runtime_error{format("option '{}' already declared with different type or flags", name)};
}
- String doc = docstring.empty() ? format("[{}]", option_type_name<T>::name())
- : format("[{}] - {}", option_type_name<T>::name(), docstring);
+ String doc = docstring.empty() ? format("[{}]", option_type_name(Meta::Type<T>{}))
+ : format("[{}] - {}", option_type_name(Meta::Type<T>{}), docstring);
m_descs.emplace_back(new OptionDesc{name.str(), std::move(doc), flags});
opts.emplace_back(new TypedCheckedOption<T, validator>{m_global_manager, *m_descs.back(), value});
return *opts.back();
diff --git a/src/option_types.hh b/src/option_types.hh
index d9dc7db7..ab2c35fa 100644
--- a/src/option_types.hh
+++ b/src/option_types.hh
@@ -16,25 +16,22 @@
namespace Kakoune
{
-template<typename T, typename = void> struct option_type_name;
-template<typename T> using void_t = void;
+template<typename T> using valid = std::true_type;
template<typename T>
-struct option_type_name<T, void_t<decltype(T::option_type_name)>>
+constexpr decltype(T::option_type_name) option_type_name(Meta::Type<T>)
{
- static decltype(T::option_type_name) name() { return T::option_type_name; }
-};
+ return T::option_type_name;
+}
template<typename Enum>
-struct option_type_name<Enum, typename std::enable_if<std::is_enum<Enum>::value>::type>
+typename std::enable_if<std::is_enum<Enum>::value, String>::type
+option_type_name(Meta::Type<Enum>)
{
- static String name()
- {
- constexpr StringView type = WithBitOps<Enum>::value ? "flags" : "enum";
- auto name = enum_desc(Enum{});
- return type + "(" + join(name | transform(std::mem_fn(&EnumDesc<Enum>::name)), '|') + ")";
- }
-};
+ constexpr StringView type = WithBitOps<Enum>::value ? "flags" : "enum";
+ auto name = enum_desc(Meta::Type<Enum>{});
+ return type + "(" + join(name | transform(std::mem_fn(&EnumDesc<Enum>::name)), '|') + ")";
+}
inline String option_to_string(int opt) { return to_string(opt); }
inline void option_from_string(StringView str, int& opt) { opt = str_to_int(str); }
@@ -44,7 +41,7 @@ inline bool option_add(int& opt, StringView str)
opt += val;
return val != 0;
}
-template<> struct option_type_name<int> { static StringView name() { return "int"; } };
+inline StringView option_type_name(Meta::Type<int>) { return "int"; }
inline String option_to_string(size_t opt) { return to_string(opt); }
inline void option_from_string(StringView str, size_t& opt) { opt = str_to_int(str); }
@@ -59,7 +56,7 @@ inline void option_from_string(StringView str, bool& opt)
else
throw runtime_error("boolean values are either true, yes, false or no");
}
-template<> struct option_type_name<bool> { static StringView name() { return "bool"; } };
+inline StringView option_type_name(Meta::Type<bool>) { return "bool"; }
constexpr char list_separator = ':';
@@ -101,10 +98,10 @@ bool option_add(Vector<T, domain>& opt, StringView str)
}
template<typename T, MemoryDomain D>
-struct option_type_name<Vector<T, D>>
+String option_type_name(Meta::Type<Vector<T, D>>)
{
- static String name() { return option_type_name<T>::name() + StringView{"-list"}; }
-};
+ return option_type_name(Meta::Type<T>{}) + StringView{"-list"};
+}
template<typename Key, typename Value, MemoryDomain domain>
String option_to_string(const HashMap<Key, Value, domain>& opt)
@@ -139,12 +136,11 @@ void option_from_string(StringView str, HashMap<Key, Value, domain>& opt)
}
template<typename K, typename V, MemoryDomain D>
-struct option_type_name<HashMap<K, V, D>>
+String option_type_name(Meta::Type<HashMap<K, V, D>>)
{
- static String name() { return format("{}-to-{}-map",
- option_type_name<K>::name(),
- option_type_name<V>::name()); }
-};
+ return format("{}-to-{}-map", option_type_name(Meta::Type<K>{}),
+ option_type_name(Meta::Type<V>{}));
+}
constexpr char tuple_separator = '|';
@@ -251,7 +247,7 @@ enum class DebugFlags
template<>
struct WithBitOps<DebugFlags> : std::true_type {};
-constexpr Array<EnumDesc<DebugFlags>, 4> enum_desc(DebugFlags)
+constexpr Array<EnumDesc<DebugFlags>, 4> enum_desc(Meta::Type<DebugFlags>)
{
return { {
{ DebugFlags::Hooks, "hooks" },