зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1221368 - Change MakeTuple to decay the types of its arguments (r=froydnj)
This commit is contained in:
Родитель
d90f4749ea
Коммит
47b5adaa34
|
@ -335,18 +335,6 @@ __declspec(noreturn) __inline void MOZ_NoReturn() {}
|
|||
namespace mozilla {
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct IsFunction
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename R, typename... A>
|
||||
struct IsFunction<R(A...)>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct AssertionConditionType
|
||||
{
|
||||
|
|
|
@ -417,9 +417,10 @@ auto Get(Tuple<Elements...>&& aTuple)
|
|||
* auto tuple = MakeTuple(42, 0.5f, 'c'); // has type Tuple<int, float, char>
|
||||
*/
|
||||
template<typename... Elements>
|
||||
Tuple<Elements...> MakeTuple(Elements&&... aElements)
|
||||
inline Tuple<typename Decay<Elements>::Type...>
|
||||
MakeTuple(Elements&&... aElements)
|
||||
{
|
||||
return Tuple<Elements...>(Forward<Elements>(aElements)...);
|
||||
return Tuple<typename Decay<Elements>::Type...>(Forward<Elements>(aElements)...);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -436,7 +437,8 @@ Tuple<Elements...> MakeTuple(Elements&&... aElements)
|
|||
* Tie(i, f, c) = FunctionThatReturnsATuple();
|
||||
*/
|
||||
template<typename... Elements>
|
||||
Tuple<Elements&...> Tie(Elements&... aVariables)
|
||||
inline Tuple<Elements&...>
|
||||
Tie(Elements&... aVariables)
|
||||
{
|
||||
return Tuple<Elements&...>(aVariables...);
|
||||
}
|
||||
|
|
|
@ -164,6 +164,40 @@ struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type>
|
|||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct IsFunPtr;
|
||||
|
||||
template<typename>
|
||||
struct IsFunPtr
|
||||
: public FalseType
|
||||
{};
|
||||
|
||||
template<typename Result, typename... ArgTypes>
|
||||
struct IsFunPtr<Result(*)(ArgTypes...)>
|
||||
: public TrueType
|
||||
{};
|
||||
|
||||
}; // namespace detail
|
||||
|
||||
/**
|
||||
* IsFunction determines whether a type is a function type. Function pointers
|
||||
* don't qualify here--only the type of an actual function symbol. We do not
|
||||
* correctly handle varags function types because of a bug in MSVC.
|
||||
*
|
||||
* Given the function:
|
||||
* void f(int) {}
|
||||
*
|
||||
* mozilla::IsFunction<void(int)> is true;
|
||||
* mozilla::IsFunction<void(*)(int)> is false;
|
||||
* mozilla::IsFunction<decltype(f)> is true.
|
||||
*/
|
||||
template<typename T>
|
||||
struct IsFunction
|
||||
: public detail::IsFunPtr<typename RemoveCV<T>::Type *>
|
||||
{};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
struct IsPointerHelper : FalseType {};
|
||||
|
||||
|
@ -1063,6 +1097,22 @@ struct RemovePointer
|
|||
: detail::RemovePointerHelper<T, typename RemoveCV<T>::Type>
|
||||
{};
|
||||
|
||||
/**
|
||||
* Converts T& to T*. Otherwise returns T* given T. Note that C++17 wants
|
||||
* std::add_pointer to work differently for function types. We don't implement
|
||||
* that behavior here.
|
||||
*
|
||||
* mozilla::AddPointer<int> is int*;
|
||||
* mozilla::AddPointer<int*> is int**;
|
||||
* mozilla::AddPointer<int&> is int*;
|
||||
* mozilla::AddPointer<int* const> is int** const.
|
||||
*/
|
||||
template<typename T>
|
||||
struct AddPointer
|
||||
{
|
||||
typedef typename RemoveReference<T>::Type* Type;
|
||||
};
|
||||
|
||||
/* 20.9.7.6 Other transformations [meta.trans.other] */
|
||||
|
||||
/**
|
||||
|
@ -1111,6 +1161,51 @@ struct Conditional<false, A, B>
|
|||
typedef B Type;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename U,
|
||||
bool IsArray = IsArray<U>::value,
|
||||
bool IsFunction = IsFunction<U>::value>
|
||||
struct DecaySelector;
|
||||
|
||||
template<typename U>
|
||||
struct DecaySelector<U, false, false>
|
||||
{
|
||||
typedef typename RemoveCV<U>::Type Type;
|
||||
};
|
||||
|
||||
template<typename U>
|
||||
struct DecaySelector<U, true, false>
|
||||
{
|
||||
typedef typename RemoveExtent<U>::Type* Type;
|
||||
};
|
||||
|
||||
template<typename U>
|
||||
struct DecaySelector<U, false, true>
|
||||
{
|
||||
typedef typename AddPointer<U>::Type Type;
|
||||
};
|
||||
|
||||
}; // namespace detail
|
||||
|
||||
/**
|
||||
* Strips const/volatile off a type and decays it from an lvalue to an
|
||||
* rvalue. So function types are converted to function pointers, arrays to
|
||||
* pointers, and references are removed.
|
||||
*
|
||||
* mozilla::Decay<int>::Type is int
|
||||
* mozilla::Decay<int&>::Type is int
|
||||
* mozilla::Decay<int&&>::Type is int
|
||||
* mozilla::Decay<const int&>::Type is int
|
||||
* mozilla::Decay<int[2]>::Type is int*
|
||||
* mozilla::Decay<int(int)>::Type is int(*)(int)
|
||||
*/
|
||||
template<typename T>
|
||||
class Decay
|
||||
: public detail::DecaySelector<typename RemoveReference<T>::Type>
|
||||
{
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_TypeTraits_h */
|
||||
|
|
|
@ -236,7 +236,7 @@ TestGet()
|
|||
CHECK(y == 42);
|
||||
}
|
||||
|
||||
static bool
|
||||
static void
|
||||
TestMakeTuple()
|
||||
{
|
||||
auto tuple = MakeTuple(42, 0.5f, 'c');
|
||||
|
@ -244,7 +244,13 @@ TestMakeTuple()
|
|||
CHECK(Get<0>(tuple) == 42);
|
||||
CHECK(Get<1>(tuple) == 0.5f);
|
||||
CHECK(Get<2>(tuple) == 'c');
|
||||
return true;
|
||||
|
||||
// Make sure we don't infer the type to be Tuple<int&>.
|
||||
int x = 1;
|
||||
auto tuple2 = MakeTuple(x);
|
||||
CHECK_TYPE(tuple2, Tuple<int>);
|
||||
x = 2;
|
||||
CHECK(Get<0>(tuple2) == 1);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
using mozilla::AddLvalueReference;
|
||||
using mozilla::AddPointer;
|
||||
using mozilla::AddRvalueReference;
|
||||
using mozilla::Decay;
|
||||
using mozilla::DeclVal;
|
||||
using mozilla::IsFunction;
|
||||
using mozilla::IsArray;
|
||||
using mozilla::IsBaseOf;
|
||||
using mozilla::IsClass;
|
||||
|
@ -27,6 +30,13 @@ using mozilla::MakeUnsigned;
|
|||
using mozilla::RemoveExtent;
|
||||
using mozilla::RemovePointer;
|
||||
|
||||
static_assert(!IsFunction<int>::value,
|
||||
"int is not a function type");
|
||||
static_assert(IsFunction<void(int)>::value,
|
||||
"void(int) is a function type");
|
||||
static_assert(!IsFunction<void(*)(int)>::value,
|
||||
"void(*)(int) is not a function type");
|
||||
|
||||
static_assert(!IsArray<bool>::value,
|
||||
"bool not an array");
|
||||
static_assert(IsArray<bool[]>::value,
|
||||
|
@ -489,6 +499,36 @@ static_assert(IsSame<RemovePointer<bool TestRemovePointer::*>::Type,
|
|||
bool TestRemovePointer::*>::value,
|
||||
"removing pointer from bool S::* must return bool S::*");
|
||||
|
||||
static_assert(IsSame<AddPointer<int>::Type, int*>::value,
|
||||
"adding pointer to int must return int*");
|
||||
static_assert(IsSame<AddPointer<int*>::Type, int**>::value,
|
||||
"adding pointer to int* must return int**");
|
||||
static_assert(IsSame<AddPointer<int&>::Type, int*>::value,
|
||||
"adding pointer to int& must return int*");
|
||||
static_assert(IsSame<AddPointer<int* const>::Type, int* const*>::value,
|
||||
"adding pointer to int* const must return int* const*");
|
||||
static_assert(IsSame<AddPointer<int* volatile>::Type, int* volatile*>::value,
|
||||
"adding pointer to int* volatile must return int* volatile*");
|
||||
|
||||
static_assert(IsSame<Decay<int>::Type, int>::value,
|
||||
"decaying int must return int");
|
||||
static_assert(IsSame<Decay<int*>::Type, int*>::value,
|
||||
"decaying int* must return int*");
|
||||
static_assert(IsSame<Decay<int* const>::Type, int*>::value,
|
||||
"decaying int* const must return int*");
|
||||
static_assert(IsSame<Decay<int* volatile>::Type, int*>::value,
|
||||
"decaying int* volatile must return int*");
|
||||
static_assert(IsSame<Decay<int&>::Type, int>::value,
|
||||
"decaying int& must return int");
|
||||
static_assert(IsSame<Decay<const int&>::Type, int>::value,
|
||||
"decaying const int& must return int");
|
||||
static_assert(IsSame<Decay<int&&>::Type, int>::value,
|
||||
"decaying int&& must return int");
|
||||
static_assert(IsSame<Decay<int[1]>::Type, int*>::value,
|
||||
"decaying int[1] must return int*");
|
||||
static_assert(IsSame<Decay<void(int)>::Type, void(*)(int)>::value,
|
||||
"decaying void(int) must return void(*)(int)");
|
||||
|
||||
/*
|
||||
* Android's broken [u]intptr_t inttype macros are broken because its PRI*PTR
|
||||
* macros are defined as "ld", but sizeof(long) is 8 and sizeof(intptr_t)
|
||||
|
|
Загрузка…
Ссылка в новой задаче