Bug 1241901 part 3 - Add IsMemberPointer and IsScalar type traits.
--- 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,