This is an automated email from the ASF dual-hosted git repository. astitcher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-proton.git
commit a9894c371acd4992fd3ed81563dcd50be61d047b Author: Andrew Stitcher <[email protected]> AuthorDate: Tue Jan 11 17:33:19 2022 -0500 PROTON-2485: Use C++11 standard type traits instead of our own versions As we only support C++11 and later we can safely use the standard c++ library type traits. This should be ABI compatible as they don't affect runtime symbols as we use them entirely at compile time. --- cpp/include/proton/codec/decoder.hpp | 12 ++--- cpp/include/proton/codec/encoder.hpp | 16 +++--- cpp/include/proton/internal/type_traits.hpp | 78 +++++------------------------ cpp/include/proton/map.hpp | 2 +- cpp/include/proton/scalar_base.hpp | 8 +-- cpp/include/proton/value.hpp | 2 +- cpp/src/scalar_test.hpp | 2 +- cpp/src/types_internal.hpp | 2 +- 8 files changed, 35 insertions(+), 87 deletions(-) diff --git a/cpp/include/proton/codec/decoder.hpp b/cpp/include/proton/codec/decoder.hpp index 82c1baa..a70046c 100644 --- a/cpp/include/proton/codec/decoder.hpp +++ b/cpp/include/proton/codec/decoder.hpp @@ -157,8 +157,8 @@ class decoder : public internal::data { assert_type_equal(MAP, s.type); r.ref.clear(); for (size_t i = 0; i < s.size/2; ++i) { - typename remove_const<typename T::key_type>::type k; - typename remove_const<typename T::mapped_type>::type v; + typename std::remove_const<typename T::key_type>::type k; + typename std::remove_const<typename T::mapped_type>::type v; *this >> k >> v; r.ref[k] = v; } @@ -175,8 +175,8 @@ class decoder : public internal::data { r.ref.clear(); for (size_t i = 0; i < s.size/2; ++i) { typedef typename T::value_type value_type; - typename remove_const<typename value_type::first_type>::type k; - typename remove_const<typename value_type::second_type>::type v; + typename std::remove_const<typename value_type::first_type>::type k; + typename std::remove_const<typename value_type::second_type>::type v; *this >> k >> v; r.ref.push_back(value_type(k, v)); } @@ -203,10 +203,10 @@ template<class T> T get(decoder& d) { /// operator>> for integer types that are not covered by the standard /// overrides. -template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, decoder&>::type +template <class T> typename std::enable_if<internal::is_unknown_integer<T>::value, decoder&>::type operator>>(decoder& d, T& i) { using namespace internal; - typename integer_type<sizeof(T), is_signed<T>::value>::type v; + typename integer_type<sizeof(T), std::is_signed<T>::value>::type v; d >> v; // Extract as a known integer type i = v; // C++ conversion to the target type. return d; diff --git a/cpp/include/proton/codec/encoder.hpp b/cpp/include/proton/codec/encoder.hpp index 1c67fd7..44317f5 100644 --- a/cpp/include/proton/codec/encoder.hpp +++ b/cpp/include/proton/codec/encoder.hpp @@ -169,10 +169,10 @@ class encoder : public internal::data { inline encoder& operator<<(encoder& e, const char* s) { return e << std::string(s); } /// operator << for integer types that are not covered by the standard overrides. -template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, encoder&>::type +template <class T> typename std::enable_if<internal::is_unknown_integer<T>::value, encoder&>::type operator<<(encoder& e, T i) { using namespace internal; - return e << static_cast<typename integer_type<sizeof(T), is_signed<T>::value>::type>(i); + return e << static_cast<typename integer_type<sizeof(T), std::is_signed<T>::value>::type>(i); } /// @cond INTERNAL @@ -192,7 +192,7 @@ template<typename T> struct is_encodable : public sfinae { }; // Avoid recursion -template <> struct is_encodable<value> : public true_type {}; +template <> struct is_encodable<value> : public std::true_type {}; } // is_encodable_impl @@ -200,15 +200,15 @@ using is_encodable_impl::is_encodable; // Metafunction to test if a class looks like an encodable map from K to T. template <class M, class K, class T, class Enable = void> -struct is_encodable_map : public internal::false_type {}; +struct is_encodable_map : public std::false_type {}; template <class M, class K, class T> struct is_encodable_map< - M, K, T, typename internal::enable_if< - internal::is_same<K, typename M::key_type>::value && - internal::is_same<T, typename M::mapped_type>::value && + M, K, T, typename std::enable_if< + std::is_same<K, typename M::key_type>::value && + std::is_same<T, typename M::mapped_type>::value && is_encodable<M>::value >::type - > : public internal::true_type {}; + > : public std::true_type {}; /// @endcond diff --git a/cpp/include/proton/internal/type_traits.hpp b/cpp/include/proton/internal/type_traits.hpp index 54d352c..b319c0f 100644 --- a/cpp/include/proton/internal/type_traits.hpp +++ b/cpp/include/proton/internal/type_traits.hpp @@ -33,6 +33,7 @@ #include <proton/type_compat.h> #include <limits> +#include <type_traits> namespace proton { namespace internal { @@ -40,56 +41,19 @@ namespace internal { class decoder; class encoder; -template <bool, class T=void> struct enable_if {}; -template <class T> struct enable_if<true, T> { typedef T type; }; - -struct true_type { static const bool value = true; }; -struct false_type { static const bool value = false; }; - -template <class T> struct is_integral : public false_type {}; -template <class T> struct is_signed : public false_type {}; - -template <> struct is_integral<char> : public true_type {}; -template <> struct is_signed<char> { static const bool value = std::numeric_limits<char>::is_signed; }; - -template <> struct is_integral<unsigned char> : public true_type {}; -template <> struct is_integral<unsigned short> : public true_type {}; -template <> struct is_integral<unsigned int> : public true_type {}; -template <> struct is_integral<unsigned long> : public true_type {}; - -template <> struct is_integral<signed char> : public true_type {}; -template <> struct is_integral<signed short> : public true_type {}; -template <> struct is_integral<signed int> : public true_type {}; -template <> struct is_integral<signed long> : public true_type {}; - -template <> struct is_signed<unsigned short> : public false_type {}; -template <> struct is_signed<unsigned int> : public false_type {}; -template <> struct is_signed<unsigned long> : public false_type {}; - -template <> struct is_signed<signed char> : public true_type {}; -template <> struct is_signed<signed short> : public true_type {}; -template <> struct is_signed<signed int> : public true_type {}; -template <> struct is_signed<signed long> : public true_type {}; - -template <> struct is_integral<unsigned long long> : public true_type {}; -template <> struct is_integral<signed long long> : public true_type {}; -template <> struct is_signed<unsigned long long> : public false_type {}; -template <> struct is_signed<signed long long> : public true_type {}; - -template <class T, class U> struct is_same { static const bool value=false; }; -template <class T> struct is_same<T,T> { static const bool value=true; }; - -template< class T > struct remove_const { typedef T type; }; -template< class T > struct remove_const<const T> { typedef T type; }; +struct type_id_unknown { + static constexpr bool has_id = false; +}; template <type_id ID, class T> struct type_id_constant { typedef T type; - static const type_id value = ID; + static constexpr type_id value = ID; + static constexpr bool has_id = true; }; /// @name Metafunction returning AMQP type for scalar C++ types. /// @{ -template <class T> struct type_id_of; +template <class T> struct type_id_of : public type_id_unknown {}; template<> struct type_id_of<null> : public type_id_constant<NULL_TYPE, null> {}; template<> struct type_id_of<decltype(nullptr)> : public type_id_constant<NULL_TYPE, null> {}; template<> struct type_id_of<bool> : public type_id_constant<BOOLEAN, bool> {}; @@ -115,8 +79,9 @@ template<> struct type_id_of<binary> : public type_id_constant<BINARY, binary> { /// @} /// Metafunction to test if a class has a type_id. -template <class T, class Enable=void> struct has_type_id : public false_type {}; -template <class T> struct has_type_id<T, typename type_id_of<T>::type> : public true_type {}; +template <class T> struct has_type_id { + static constexpr bool value = type_id_of<T>::has_id; +}; // The known/unknown integer type magic is required because the C++ standard is // vague a about the equivalence of integral types for overloading. E.g. char is @@ -144,11 +109,11 @@ template<> struct integer_type<8, false> { typedef uint64_t type; }; // True if T is an integer type that does not have an explicit type_id. template <class T> struct is_unknown_integer { - static const bool value = !has_type_id<T>::value && is_integral<T>::value; + static constexpr bool value = !has_type_id<T>::value && std::is_integral<T>::value; }; -template<class T, class = typename enable_if<is_unknown_integer<T>::value>::type> -struct known_integer : public integer_type<sizeof(T), is_signed<T>::value> {}; +template<class T, class = typename std::enable_if<is_unknown_integer<T>::value>::type> +struct known_integer : public integer_type<sizeof(T), std::is_signed<T>::value> {}; // Helper base for SFINAE templates. struct sfinae { @@ -159,23 +124,6 @@ struct sfinae { }; }; -template <class From, class To> struct is_convertible : public sfinae { - static yes test(const To&); - static no test(...); - static const From& from; - // Windows compilers warn about data-loss caused by legal conversions. We - // can't use static_cast because that will cause a hard error instead of - // letting SFINAE overload resolution select the test(...) overload. -#ifdef _WIN32 -#pragma warning( push ) -#pragma warning( disable : 4244 ) -#endif - static bool const value = sizeof(test(from)) == sizeof(yes); -#ifdef _WIN32 -#pragma warning( pop ) -#endif -}; - } // internal } // proton diff --git a/cpp/include/proton/map.hpp b/cpp/include/proton/map.hpp index b114d1c..5bff48f 100644 --- a/cpp/include/proton/map.hpp +++ b/cpp/include/proton/map.hpp @@ -67,7 +67,7 @@ template <class K, class T> class PN_CPP_CLASS_EXTERN map { template <class M, class U=void> struct assignable_map : - public internal::enable_if<codec::is_encodable_map<M,K,T>::value, U> {}; + public std::enable_if<codec::is_encodable_map<M,K,T>::value, U> {}; public: /// Construct an empty map. diff --git a/cpp/include/proton/scalar_base.hpp b/cpp/include/proton/scalar_base.hpp index b98c44d..388a1f8 100644 --- a/cpp/include/proton/scalar_base.hpp +++ b/cpp/include/proton/scalar_base.hpp @@ -134,7 +134,7 @@ class scalar_base : private internal::comparable<scalar_base> { static void put(scalar_base& s, const T& x) { s.put_(x); } }; template <class T> - struct putter<T, typename internal::enable_if<internal::is_unknown_integer<T>::value>::type> { + struct putter<T, typename std::enable_if<internal::is_unknown_integer<T>::value>::type> { static void put(scalar_base& s, const T& x) { s.put_(static_cast<typename internal::known_integer<T>::type>(x)); } @@ -144,7 +144,7 @@ class scalar_base : private internal::comparable<scalar_base> { static T get(const scalar_base& s) { T x; s.get_(x); return x; } }; template <class T> - struct getter<T, typename internal::enable_if<internal::is_unknown_integer<T>::value>::type> { + struct getter<T, typename std::enable_if<internal::is_unknown_integer<T>::value>::type> { static T get(const scalar_base& s) { typename internal::known_integer<T>::type x; s.get_(x); return x; } @@ -201,11 +201,11 @@ PN_CPP_EXTERN conversion_error make_coercion_error(const char* cpp_type, type_id template<class T> struct coerce_op { template <class U> - typename enable_if<is_convertible<U, T>::value, T>::type operator()(const U& x) { + typename std::enable_if<std::is_convertible<U, T>::value, T>::type operator()(const U& x) { return static_cast<T>(x); } template <class U> - typename enable_if<!is_convertible<U, T>::value, T>::type operator()(const U&) { + typename std::enable_if<!std::is_convertible<U, T>::value, T>::type operator()(const U&) { throw make_coercion_error(typeid(T).name(), type_id_of<U>::value); } }; diff --git a/cpp/include/proton/value.hpp b/cpp/include/proton/value.hpp index 5204a72..d56822f 100644 --- a/cpp/include/proton/value.hpp +++ b/cpp/include/proton/value.hpp @@ -58,7 +58,7 @@ class value : public internal::value_base, private internal::comparable<value> { private: // Enabler for encodable types excluding proton::value. template<class T, class U=void> struct assignable : - public internal::enable_if<codec::is_encodable<T>::value, U> {}; + public std::enable_if<codec::is_encodable<T>::value, U> {}; template<class U> struct assignable<value, U> {}; public: diff --git a/cpp/src/scalar_test.hpp b/cpp/src/scalar_test.hpp index 206a161..68f48e4 100644 --- a/cpp/src/scalar_test.hpp +++ b/cpp/src/scalar_test.hpp @@ -79,7 +79,7 @@ template <class V, class T> void simple_type_test(T x, type_id tid, const std::s // Test native C/C++ integer types via their mapped integer type ([u]int_x_t) template <class V, class T> void simple_integral_test() { - typedef typename internal::integer_type<sizeof(T), internal::is_signed<T>::value>::type int_type; + typedef typename internal::integer_type<sizeof(T), std::is_signed<T>::value>::type int_type; simple_type_test<V>(T(3), internal::type_id_of<int_type>::value, "3", T(4)); } diff --git a/cpp/src/types_internal.hpp b/cpp/src/types_internal.hpp index bff93a0..0d44215 100644 --- a/cpp/src/types_internal.hpp +++ b/cpp/src/types_internal.hpp @@ -31,7 +31,7 @@ namespace proton { /// Byte copy between two objects, only enabled if their sizes are equal. template <class T, class U> -typename internal::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) { +typename std::enable_if<sizeof(T) == sizeof(U)>::type byte_copy(T &to, const U &from) { const char *p = reinterpret_cast<const char*>(&from); std::copy(p, p + sizeof(T), reinterpret_cast<char*>(&to)); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
