Reader reflection of std::variant<Ts...>

This commit is contained in:
Fangrui Song 2018-01-10 23:16:33 -08:00
parent b2672c6009
commit 27ddce4cd6
6 changed files with 47 additions and 35 deletions

View File

@ -7,29 +7,6 @@
#include <iostream> #include <iostream>
void Reflect(Reader& visitor, std::variant<std::monostate, int>& version) {
if (visitor.IsNull()) {
visitor.GetNull();
version = std::monostate();
} else
version = visitor.GetInt();
}
void Reflect(Reader& visitor, lsRequestId& id) {
if (visitor.IsNull()) {
visitor.GetNull();
id = std::monostate();
} else if (visitor.IsString()) {
std::string v;
Reflect(visitor, v);
id = v;
} else {
int64_t v;
Reflect(visitor, v);
id = v;
}
}
MessageRegistry* MessageRegistry::instance_ = nullptr; MessageRegistry* MessageRegistry::instance_ = nullptr;
lsTextDocumentIdentifier lsTextDocumentIdentifier

View File

@ -24,7 +24,6 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
using lsRequestId = std::variant<std::monostate, int64_t, std::string>; using lsRequestId = std::variant<std::monostate, int64_t, std::string>;
void Reflect(Reader& visitor, lsRequestId& id);
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
@ -253,7 +252,6 @@ struct lsTextDocumentIdentifier {
}; };
MAKE_REFLECT_STRUCT(lsTextDocumentIdentifier, uri); MAKE_REFLECT_STRUCT(lsTextDocumentIdentifier, uri);
void Reflect(Reader& visitor, std::variant<std::monostate, int>& version);
struct lsVersionedTextDocumentIdentifier { struct lsVersionedTextDocumentIdentifier {
lsDocumentUri uri; lsDocumentUri uri;
// The version number of this document. number | null // The version number of this document. number | null

View File

@ -4,8 +4,10 @@
#include <optional.h> #include <optional.h>
#include <variant.h> #include <variant.h>
#include <cassert>
#include <memory> #include <memory>
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
enum class SerializeFormat { Json, MessagePack }; enum class SerializeFormat { Json, MessagePack };
@ -19,7 +21,7 @@ class Reader {
virtual bool IsNull() = 0; virtual bool IsNull() = 0;
virtual bool IsArray() = 0; virtual bool IsArray() = 0;
virtual bool IsInt() = 0; virtual bool IsInt() = 0;
// virtual bool IsInt64() = 0; virtual bool IsInt64() = 0;
// virtual bool IsUint64() = 0; // virtual bool IsUint64() = 0;
virtual bool IsString() = 0; virtual bool IsString() = 0;
@ -187,8 +189,44 @@ void Reflect(Writer& visitor, optional<T>& value) {
visitor.Null(); visitor.Null();
} }
namespace {
template <typename B0, typename... Bs>
struct disjunction
: std::conditional<bool(B0::value), B0, disjunction<Bs...>>::type {};
template <typename B0>
struct disjunction<B0> : B0 {};
}
template <size_t N, typename... Ts> template <size_t N, typename... Ts>
struct ReflectVariant { struct ReflectVariant {
template <typename T>
typename std::enable_if<disjunction<std::is_same<T, Ts>...>::value,
void>::type
ReflectTag(Reader& visitor, std::variant<Ts...>& value) {
T a;
Reflect(visitor, a);
value = a;
}
template <typename T>
typename std::enable_if<!disjunction<std::is_same<T, Ts>...>::value,
void>::type
ReflectTag(Reader&, std::variant<Ts...>&) {}
void operator()(Reader& visitor, std::variant<Ts...>& value) {
if (visitor.IsNull())
ReflectTag<std::monostate>(visitor, value);
// It is possible that IsInt64() && IsInt(). We don't call ReflectTag<int> if
// int is not in Ts...
else if (disjunction<std::is_same<int, Ts>...>::value && visitor.IsInt())
ReflectTag<int>(visitor, value);
else if (visitor.IsInt64())
ReflectTag<int64_t>(visitor, value);
else if (visitor.IsString())
ReflectTag<std::string>(visitor, value);
else
assert(0);
}
void operator()(Writer& visitor, std::variant<Ts...>& value) { void operator()(Writer& visitor, std::variant<Ts...>& value) {
if (value.index() == N - 1) if (value.index() == N - 1)
Reflect(visitor, std::get<N - 1>(value)); Reflect(visitor, std::get<N - 1>(value));
@ -198,15 +236,13 @@ struct ReflectVariant {
}; };
template <typename... Ts> template <typename... Ts>
struct ReflectVariant<1, Ts...> { struct ReflectVariant<0, Ts...> {
void operator()(Writer& visitor, std::variant<Ts...>& value) { void operator()(Writer& visitor, std::variant<Ts...>& value) {}
Reflect(visitor, std::get<0>(value));
}
}; };
// std::variant (Writer only) // std::variant
template <typename... Ts> template <typename TVisitor, typename... Ts>
void Reflect(Writer& visitor, std::variant<Ts...>& value) { void Reflect(TVisitor& visitor, std::variant<Ts...>& value) {
ReflectVariant<sizeof...(Ts), Ts...>()(visitor, value); ReflectVariant<sizeof...(Ts), Ts...>()(visitor, value);
} }

View File

@ -16,7 +16,7 @@ class JsonReader : public Reader {
bool IsNull() override { return m_->IsNull(); } bool IsNull() override { return m_->IsNull(); }
bool IsArray() override { return m_->IsArray(); } bool IsArray() override { return m_->IsArray(); }
bool IsInt() override { return m_->IsInt(); } bool IsInt() override { return m_->IsInt(); }
// bool IsInt64() override { return m_->IsInt64(); } bool IsInt64() override { return m_->IsInt64(); }
// bool IsUint64() override { return m_->IsUint64(); } // bool IsUint64() override { return m_->IsUint64(); }
bool IsString() override { return m_->IsString(); } bool IsString() override { return m_->IsString(); }

View File

@ -27,6 +27,7 @@ class MessagePackReader : public Reader {
return oh_.get().type == msgpack::type::POSITIVE_INTEGER || return oh_.get().type == msgpack::type::POSITIVE_INTEGER ||
oh_.get().type == msgpack::type::NEGATIVE_INTEGER; oh_.get().type == msgpack::type::NEGATIVE_INTEGER;
} }
bool IsInt64() override { return IsInt(); }
bool IsString() override { return oh_.get().type == msgpack::type::STR; } bool IsString() override { return oh_.get().type == msgpack::type::STR; }
void GetNull() override { pk_->next(oh_); } void GetNull() override { pk_->next(oh_); }