From 0834828099e03e2af322fef5268c91461c661231 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Fri, 24 Mar 2023 09:52:12 +0800 Subject: [PATCH] adaptor: better diagnostic for converter we only use the default `convert` implementation, if a `msgpack_unpack` method actually exists. if that's not the case we get an `undefined template` error. --- include/msgpack/v1/adaptor/adaptor_base.hpp | 40 +++++++++++++++++++++ include/msgpack/v1/cpp_config.hpp | 20 +++++++++++ include/msgpack/v1/cpp_config_decl.hpp | 20 +++++++++++ include/msgpack/v1/object.hpp | 7 ++++ test/object.cpp | 15 ++++++++ 5 files changed, 102 insertions(+) diff --git a/include/msgpack/v1/adaptor/adaptor_base.hpp b/include/msgpack/v1/adaptor/adaptor_base.hpp index 489362b4d..00a9af88f 100644 --- a/include/msgpack/v1/adaptor/adaptor_base.hpp +++ b/include/msgpack/v1/adaptor/adaptor_base.hpp @@ -12,6 +12,9 @@ #include "msgpack/v1/adaptor/adaptor_base_decl.hpp" +#include "msgpack/v1/cpp_config.hpp" + + namespace msgpack { /// @cond @@ -21,13 +24,50 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { namespace adaptor { +// Unpack detector + +#ifndef MSGPACK_USE_CPP03 + +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 = void_t<> > +struct has_msgpack_unpack : std::false_type +{}; + +template < typename T > +struct has_msgpack_unpack< T, void_t< impl::msgpack_unpack_t< T > > > : std::true_type +{}; + +} // namespace impl + +#endif + // Adaptor functors +#ifdef MSGPACK_USE_CPP03 + template struct convert { msgpack::object const& operator()(msgpack::object const& o, T& v) const; }; +#else + +template +struct convert; + +template +struct convert::value>::type> +{ + msgpack::object const &operator()(msgpack::object const &o, T &v) const; +}; + +#endif + template struct pack { template diff --git a/include/msgpack/v1/cpp_config.hpp b/include/msgpack/v1/cpp_config.hpp index 18d2a9a6d..7a17ac704 100644 --- a/include/msgpack/v1/cpp_config.hpp +++ b/include/msgpack/v1/cpp_config.hpp @@ -138,4 +138,24 @@ template struct is_pointer : detail::is_pointer_helper= 201402L + +#if !defined(MSGPACK_USE_CPP03) && MSGPACK_CPP_VERSION < 201703L + +namespace msgpack { + +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + +template using void_t = void; + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond + +} // namespace msgpack + +#endif + + #endif // MSGPACK_V1_CPP_CONFIG_HPP diff --git a/include/msgpack/v1/cpp_config_decl.hpp b/include/msgpack/v1/cpp_config_decl.hpp index 383a44511..b1bdce97d 100644 --- a/include/msgpack/v1/cpp_config_decl.hpp +++ b/include/msgpack/v1/cpp_config_decl.hpp @@ -87,6 +87,7 @@ struct is_pointer; #include #include +#include namespace msgpack { /// @cond @@ -124,4 +125,23 @@ MSGPACK_API_VERSION_NAMESPACE(v1) { #define MSGPACK_HAS_INCLUDE(header) 0 #endif // defined(__has_include) +#if MSGPACK_CPP_VERSION >= 201703L + +namespace msgpack { +/// @cond +MSGPACK_API_VERSION_NAMESPACE(v1) { +/// @endcond + + // type_traits + using std::void_t; + +/// @cond +} // MSGPACK_API_VERSION_NAMESPACE(v1) +/// @endcond +} // namespace msgpack + + +#endif + + #endif // MSGPACK_V1_CPP_CONFIG_DECL_HPP diff --git a/include/msgpack/v1/object.hpp b/include/msgpack/v1/object.hpp index fda54be9f..8dc655b7c 100644 --- a/include/msgpack/v1/object.hpp +++ b/include/msgpack/v1/object.hpp @@ -640,10 +640,17 @@ struct packer_serializer { } // namespace detail // Adaptor functors' member functions definitions. +#ifdef MSGPACK_USE_CPP03 template inline msgpack::object const& adaptor::convert::operator()(msgpack::object const& o, T& v) const { +#else +template +inline +msgpack::object const& +adaptor::convert::value>::type>::operator()(msgpack::object const& o, T& v) const { +#endif v.msgpack_unpack(o.convert()); return o; } diff --git a/test/object.cpp b/test/object.cpp index 1f6d7bbd8..ff6ea1970 100644 --- a/test/object.cpp +++ b/test/object.cpp @@ -562,3 +562,18 @@ BOOST_AUTO_TEST_CASE(array_unsigned_char) } #endif // MSGPACK_CPP_VERSION >= 201703 + +#ifndef MSGPACK_USE_CPP03 + +struct struct_without_adaptor +{ + int foo; +}; + +BOOST_AUTO_TEST_CASE(has_msgpack_unpack) +{ + static_assert(msgpack::v1::adaptor::impl::has_msgpack_unpack::value == false, ""); + static_assert(msgpack::v1::adaptor::impl::has_msgpack_unpack::value, ""); +} + +#endif