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]

Reply via email to