You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2022/01/18 14:04:18 UTC
[qpid-proton] 02/05: PROTON-2485: Use C++11 standard type traits instead of our own versions
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 <as...@apache.org>
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: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org