Bug 1241901 part 3 - Add IsMemberPointer and IsScalar type traits. draft
authorXidorn Quan <quanxunzhen@gmail.com>
Thu, 28 Jan 2016 17:51:58 +1100
changeset 326693 f5bd175d33ff28bcc7b0405b2621de6917e9e0df
parent 326692 800b4bcba7ed1cd8737375afb3ca0e2ba2b6cc17
child 326694 018e6c20446a9b5762a476a13cabeb8373eb9f5f
push id10164
push userxquan@mozilla.com
push dateThu, 28 Jan 2016 11:17:52 +0000
bugs1241901
milestone47.0a1
Bug 1241901 part 3 - Add IsMemberPointer and IsScalar type traits.
mfbt/TypeTraits.h
mfbt/tests/TestTypeTraits.cpp
--- a/mfbt/TypeTraits.h
+++ b/mfbt/TypeTraits.h
@@ -350,16 +350,51 @@ struct IsReference
  * mozilla::IsArithmetic<double>::value is true;
  * mozilla::IsArithmetic<long double*>::value is false.
  */
 template<typename T>
 struct IsArithmetic
   : IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>
 {};
 
+namespace detail {
+
+template<typename T>
+struct IsMemberPointerHelper : FalseType {};
+
+template<typename T, typename U>
+struct IsMemberPointerHelper<T U::*> : TrueType {};
+
+} // namespace detail
+
+/**
+ * IsMemberPointer determines whether a type is pointer to non-static member
+ * object or a pointer to non-static member function.
+ *
+ * mozilla::IsMemberPointer<int(cls::*)>::value is true
+ * mozilla::IsMemberPointer<int*>::value is false
+ */
+template<typename T>
+struct IsMemberPointer
+  : detail::IsMemberPointerHelper<typename RemoveCV<T>::Type>
+{};
+
+/**
+ * IsScalar determines whether a type is a scalar type.
+ *
+ * mozilla::IsScalar<int>::value is true
+ * mozilla::IsScalar<int*>::value is true
+ * mozilla::IsScalar<cls>::value is false
+ */
+template<typename T>
+struct IsScalar
+  : IntegralConstant<bool, IsArithmetic<T>::value || IsEnum<T>::value ||
+                     IsPointer<T>::value || IsMemberPointer<T>::value>
+{};
+
 /* 20.9.4.3 Type properties [meta.unary.prop] */
 
 /**
  * IsConst determines whether a type is const or not.
  *
  * mozilla::IsConst<int>::value is false;
  * mozilla::IsConst<void* const>::value is true;
  * mozilla::IsConst<const char*>::value is false.
--- a/mfbt/tests/TestTypeTraits.cpp
+++ b/mfbt/tests/TestTypeTraits.cpp
@@ -2,16 +2,22 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Assertions.h"
 #include "mozilla/TypeTraits.h"
 
+#define TEST_CV_QUALIFIERS(test, type, ...) \
+  test(type, __VA_ARGS__) \
+  test(const type, __VA_ARGS__) \
+  test(volatile type, __VA_ARGS__) \
+  test(const volatile type, __VA_ARGS__)
+
 using mozilla::AddLvalueReference;
 using mozilla::AddPointer;
 using mozilla::AddRvalueReference;
 using mozilla::Decay;
 using mozilla::DeclVal;
 using mozilla::IsFunction;
 using mozilla::IsArray;
 using mozilla::IsBaseOf;
@@ -132,16 +138,87 @@ static_assert(!IsReference<int>::value,
               "int not a reference");
 static_assert(!IsReference<int*>::value,
               "int* not a reference");
 static_assert(IsReference<int&>::value,
               "int& is a reference");
 static_assert(IsReference<int&&>::value,
               "int&& is a reference");
 
+namespace CPlusPlus11IsMemberPointer {
+
+using mozilla::IsMemberPointer;
+
+struct S {};
+union U {};
+
+#define ASSERT_IS_MEMBER_POINTER(type, msg) \
+  static_assert(IsMemberPointer<type>::value, #type msg);
+#define TEST_IS_MEMBER_POINTER(type) \
+  TEST_CV_QUALIFIERS(ASSERT_IS_MEMBER_POINTER, type, \
+                     " is a member pointer type")
+
+TEST_IS_MEMBER_POINTER(int S::*)
+TEST_IS_MEMBER_POINTER(int U::*)
+
+#undef TEST_IS_MEMBER_POINTER
+#undef ASSERT_IS_MEMBER_POINTER
+
+#define ASSERT_IS_NOT_MEMBER_POINTER(type, msg) \
+  static_assert(!IsMemberPointer<type>::value, #type msg);
+#define TEST_IS_NOT_MEMBER_POINTER(type) \
+  TEST_CV_QUALIFIERS(ASSERT_IS_NOT_MEMBER_POINTER, type, \
+                     " is not a member pointer type")
+
+TEST_IS_NOT_MEMBER_POINTER(int*)
+
+#undef TEST_IS_NOT_MEMBER_POINTER
+#undef ASSERT_IS_NOT_MEMBER_POINTER
+
+} // CPlusPlus11IsMemberPointer
+
+namespace CPlusPlus11IsScalar {
+
+using mozilla::IsScalar;
+
+enum E {};
+enum class EC {};
+class C {};
+struct S {};
+union U {};
+
+#define ASSERT_IS_SCALAR(type, msg) \
+  static_assert(IsScalar<type>::value, #type msg);
+#define TEST_IS_SCALAR(type) \
+  TEST_CV_QUALIFIERS(ASSERT_IS_SCALAR, type, " is a scalar type")
+
+TEST_IS_SCALAR(int)
+TEST_IS_SCALAR(float)
+TEST_IS_SCALAR(E)
+TEST_IS_SCALAR(EC)
+TEST_IS_SCALAR(S*)
+TEST_IS_SCALAR(int S::*)
+
+#undef TEST_IS_SCALAR
+#undef ASSERT_IS_SCALAR
+
+#define ASSERT_IS_NOT_SCALAR(type, msg) \
+  static_assert(!IsScalar<type>::value, #type msg);
+#define TEST_IS_NOT_SCALAR(type) \
+  TEST_CV_QUALIFIERS(ASSERT_IS_NOT_SCALAR, type, " is not a scalar type")
+
+TEST_IS_NOT_SCALAR(C)
+TEST_IS_NOT_SCALAR(S)
+TEST_IS_NOT_SCALAR(U)
+
+#undef TEST_IS_NOT_SCALAR
+#undef ASSERT_IS_NOT_SCALAR
+
+} // CPlusPlus11IsScalar
+
 struct S1 {};
 union U1 { int mX; };
 
 static_assert(!IsClass<int>::value,
               "int isn't a class");
 static_assert(IsClass<const S1>::value,
               "S is a class");
 static_assert(!IsClass<U1>::value,