-
Notifications
You must be signed in to change notification settings - Fork 908
Open
Description
more a question than a bug, but something that i've been wondering without having found a good answer, yet:
i'd like to detect at compile time via a constexpr function if an adaptor for a specific type exists:
template <typename T>
constexpr bool msgpack_can_pack();
currently we have:
template <typename T, typename Enabler>
struct convert {
msgpack::object const& operator()(msgpack::object const& o, T& v) const;
};
operator()
is either implemented by a specialization or it is using the default implementation at:
template <typename T, typename Enabler>
inline
msgpack::object const&
adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
v.msgpack_unpack(o.convert());
return o;
}
so afaict we may need two answer two question:
- can we use
enable_if
to check if theoperator()
can be implemented for a specific type? - can we check if
operator()
exists in order to implementmsgpack_can_pack
?
thoughts?
i've done a few experiments:
diff --git a/include/msgpack/v1/adaptor/adaptor_base.hpp b/include/msgpack/v1/adaptor/adaptor_base.hpp
index 489362b..b2291ec 100644
--- a/include/msgpack/v1/adaptor/adaptor_base.hpp
+++ b/include/msgpack/v1/adaptor/adaptor_base.hpp
@@ -18,17 +18,43 @@ namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(v1) {
/// @endcond
namespace adaptor {
+namespace impl {
+
+template < typename T >
+using msgpack_unpack_t
+ = decltype( std::declval< T >().msgpack_unpack( std::declval< msgpack::object::implicit_type >() ) );
+
+template < typename T, typename = std::void_t<> >
+struct has_msgpack_unpack : std::false_type
+{};
+
+template < typename T >
+struct has_msgpack_unpack< T, std::void_t< msgpack_unpack_t< T > > > : std::true_type
+{};
+
+template < typename T >
+inline constexpr bool has_msgpack_unpack_v = has_msgpack_unpack< T >::value;
+
+} // namespace impl
+
+
// Adaptor functors
-template <typename T, typename Enabler>
-struct convert {
- msgpack::object const& operator()(msgpack::object const& o, T& v) const;
+template<typename T, typename Enabler>
+struct convert
+{
+};
+
+template<typename T>
+struct convert<T, std::enable_if_t<impl::has_msgpack_unpack_v<T>>>
+{
+ msgpack::object const &operator()(msgpack::object const &o, T &v) const;
};
template <typename T, typename Enabler>
struct pack {
template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, T const& v) const;
diff --git a/include/msgpack/v1/object.hpp b/include/msgpack/v1/object.hpp
index fda54be..a9ac15a 100644
--- a/include/msgpack/v1/object.hpp
+++ b/include/msgpack/v1/object.hpp
@@ -637,16 +637,16 @@ struct packer_serializer {
return o;
}
};
} // namespace detail
// Adaptor functors' member functions definitions.
-template <typename T, typename Enabler>
+template <typename T>
inline
msgpack::object const&
-adaptor::convert<T, Enabler>::operator()(msgpack::object const& o, T& v) const {
+adaptor::convert<T, std::enable_if_t<adaptor::impl::has_msgpack_unpack_v<T>>>::operator()(msgpack::object const& o, T& v) const {
v.msgpack_unpack(o.convert());
return o;
}
template <typename T, typename Enabler>
template <typename Stream>
this would allow me to write something like:
template < typename T, typename = void >
struct has_msgpack_convert_helper : std::false_type
{};
template < typename T >
struct has_msgpack_convert_helper< T,
std::void_t< decltype( std::declval< msgpack::v3::adaptor::convert< T > >()(
std::declval< msgpack::object const& >(), std::declval< T& >() ) ) > >
: std::true_type
{};
template < typename T >
constexpr bool has_msgpack_convert = has_msgpack_convert_helper< T >::value;
any thoughts on such functionality in the library?
Metadata
Metadata
Assignees
Labels
No labels