Bug 953296 - Implement mozilla::MakeUnique. r=jcranmer

--HG--
extra : rebase_source : 6e25d80e697f1b00e1525f6b11221f4ed9cf965e
This commit is contained in:
Jeff Walden 2014-06-10 17:42:58 -07:00
parent b8f04e804d
commit 0266bcb7ec
2 changed files with 138 additions and 0 deletions

View File

@ -569,6 +569,99 @@ operator!=(NullptrT n, const UniquePtr<T, D>& x)
// No operator<, operator>, operator<=, operator>= for now because simplicity.
namespace detail {
template<typename T>
struct UniqueSelector
{
typedef UniquePtr<T> SingleObject;
};
template<typename T>
struct UniqueSelector<T[]>
{
typedef UniquePtr<T[]> UnknownBound;
};
template<typename T, decltype(sizeof(int)) N>
struct UniqueSelector<T[N]>
{
typedef UniquePtr<T[N]> KnownBound;
};
} // namespace detail
// We don't have variadic template support everywhere, so just hard-code arities
// 0-4 for now. If you need more arguments, feel free to add the extra
// overloads.
//
// Beware! Due to lack of true nullptr support in gcc 4.4 and 4.5, passing
// literal nullptr to MakeUnique will not work on some platforms. See Move.h
// for more details.
template<typename T>
typename detail::UniqueSelector<T>::SingleObject
MakeUnique()
{
return UniquePtr<T>(new T());
}
template<typename T, typename A1>
typename detail::UniqueSelector<T>::SingleObject
MakeUnique(A1&& a1)
{
return UniquePtr<T>(new T(Forward<A1>(a1)));
}
template<typename T, typename A1, typename A2>
typename detail::UniqueSelector<T>::SingleObject
MakeUnique(A1&& a1, A2&& a2)
{
return UniquePtr<T>(new T(Forward<A1>(a1), Forward<A2>(a2)));
}
template<typename T, typename A1, typename A2, typename A3>
typename detail::UniqueSelector<T>::SingleObject
MakeUnique(A1&& a1, A2&& a2, A3&& a3)
{
return UniquePtr<T>(new T(Forward<A1>(a1), Forward<A2>(a2), Forward<A3>(a3)));
}
template<typename T, typename A1, typename A2, typename A3, typename A4>
typename detail::UniqueSelector<T>::SingleObject
MakeUnique(A1&& a1, A2&& a2, A3&& a3, A4&& a4)
{
return UniquePtr<T>(new T(Forward<A1>(a1), Forward<A2>(a2), Forward<A3>(a3), Forward<A4>(a4)));
}
template<typename T>
typename detail::UniqueSelector<T>::UnknownBound
MakeUnique(decltype(sizeof(int)) n)
{
typedef typename RemoveExtent<T>::Type ArrayType;
return UniquePtr<T>(new ArrayType[n]());
}
template<typename T>
typename detail::UniqueSelector<T>::KnownBound
MakeUnique() MOZ_DELETE;
template<typename T, typename A1>
typename detail::UniqueSelector<T>::KnownBound
MakeUnique(A1&& a1) MOZ_DELETE;
template<typename T, typename A1, typename A2>
typename detail::UniqueSelector<T>::KnownBound
MakeUnique(A1&& a1, A2&& a2) MOZ_DELETE;
template<typename T, typename A1, typename A2, typename A3>
typename detail::UniqueSelector<T>::KnownBound
MakeUnique(A1&& a1, A2&& a2, A3&& a3) MOZ_DELETE;
template<typename T, typename A1, typename A2, typename A3, typename A4>
typename detail::UniqueSelector<T>::KnownBound
MakeUnique(A1&& a1, A2&& a2, A3&& a3, A4&& a4) MOZ_DELETE;
} // namespace mozilla
#endif /* mozilla_UniquePtr_h */

View File

@ -16,6 +16,7 @@
using mozilla::DefaultDelete;
using mozilla::IsNullPointer;
using mozilla::IsSame;
using mozilla::MakeUnique;
using mozilla::Swap;
using mozilla::UniquePtr;
using mozilla::Vector;
@ -543,6 +544,48 @@ TestArray()
return true;
}
struct Q
{
Q() {}
Q(const Q& q) {}
Q(Q& q, char c) {}
template<typename T>
Q(Q q, T&& t, int i)
{}
Q(int i, long j, double k, void* l) {}
};
static int randomInt() { return 4; }
static bool
TestMakeUnique()
{
UniquePtr<int> a1(MakeUnique<int>());
UniquePtr<long> a2(MakeUnique<long>(4));
// no args, easy
UniquePtr<Q> q0(MakeUnique<Q>());
// temporary bound to const lval ref
UniquePtr<Q> q1(MakeUnique<Q>(Q()));
// passing through a non-const lval ref
UniquePtr<Q> q2(MakeUnique<Q>(*q1, 'c'));
// pass by copying, forward a temporary, pass by value
UniquePtr<Q> q3(MakeUnique<Q>(Q(), UniquePtr<int>(), randomInt()));
// various type mismatching to test "fuzzy" forwarding
UniquePtr<Q> q4(MakeUnique<Q>('s', 66LL, 3.141592654, &q3));
UniquePtr<char[]> c1(MakeUnique<char[]>(5));
return true;
}
int
main()
{
@ -558,4 +601,6 @@ main()
return 1;
if (!TestArray())
return 1;
if (!TestMakeUnique())
return 1;
}