author | Botond Ballo <botond@mozilla.com> |
Fri, 06 Nov 2015 17:47:36 -0500 | |
changeset 273031 | 43ca206bb8127d4de6ae1fa5e4af4b0f8ef9d14c |
parent 273030 | bb2ece1c131b9faf7d560ac10c4d8daa6f6a09b0 |
child 273032 | 40a37cb11607a03baa857eb41095956923676e5c |
push id | 29693 |
push user | cbook@mozilla.com |
push date | Wed, 18 Nov 2015 13:50:33 +0000 |
treeherder | mozilla-central@1d6155d7e6c9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | froydnj |
bugs | 1221680 |
milestone | 45.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
mfbt/TypeTraits.h | file | annotate | diff | comparison | revisions | |
mfbt/tests/TestTypeTraits.cpp | file | annotate | diff | comparison | revisions |
--- a/mfbt/TypeTraits.h +++ b/mfbt/TypeTraits.h @@ -19,16 +19,28 @@ #include <wchar.h> namespace mozilla { /* Forward declarations. */ template<typename> struct RemoveCV; +template<typename> struct AddRvalueReference; + +/* 20.2.4 Function template declval [declval] */ + +/** + * DeclVal simplifies the definition of expressions which occur as unevaluated + * operands. It converts T to a reference type, making it possible to use in + * decltype expressions even if T does not have a default constructor, e.g.: + * decltype(DeclVal<TWithNoDefaultConstructor>().foo()) + */ +template<typename T> +typename AddRvalueReference<T>::Type DeclVal(); /* 20.9.3 Helper classes [meta.help] */ /** * Helper class used as a base for various type traits, exposed publicly * because <type_traits> exposes it as well. */ template<typename T, T Value> @@ -627,31 +639,35 @@ struct BaseOfTester<Type, const Type> : */ template<class Base, class Derived> struct IsBaseOf : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value> {}; namespace detail { +// This belongs inside ConvertibleTester, but it's pulled out to +// work around a bug in the compiler used for hazard builds. +template <typename To> +static void ConvertibleTestHelper(To); + template<typename From, typename To> struct ConvertibleTester { private: - static From create(); - - template<typename From1, typename To1> - static char test(To to); + template<typename From1, typename To1, + typename = decltype(ConvertibleTestHelper<To1>(DeclVal<From>()))> + static char test(int); template<typename From1, typename To1> static int test(...); public: static const bool value = - sizeof(test<From, To>(create())) == sizeof(char); + sizeof(test<From, To>(0)) == sizeof(char); }; } // namespace detail /** * IsConvertible determines whether a value of type From will implicitly convert * to a value of type To. For example: * @@ -859,27 +875,16 @@ struct AddRvalueReferenceHelper<T, TIsNo * mozilla::AddRvalueReference<void>::Type is void; * mozilla::AddRvalueReference<struct S&>::Type is struct S&. */ template<typename T> struct AddRvalueReference : detail::AddRvalueReferenceHelper<T> {}; -/* 20.2.4 Function template declval [declval] */ - -/** - * DeclVal simplifies the definition of expressions which occur as unevaluated - * operands. It converts T to a reference type, making it possible to use in - * decltype expressions even if T does not have a default constructor, e.g.: - * decltype(DeclVal<TWithNoDefaultConstructor>().foo()) - */ -template<typename T> -typename AddRvalueReference<T>::Type DeclVal(); - /* 20.9.7.3 Sign modifications [meta.trans.sign] */ template<bool B, typename T = void> struct EnableIf; namespace detail { template<bool MakeConst, typename T>
--- a/mfbt/tests/TestTypeTraits.cpp +++ b/mfbt/tests/TestTypeTraits.cpp @@ -332,16 +332,20 @@ TestIsBaseOf() static_assert((!IsBaseOf<A, D>::value), "A is not a base of D"); static_assert((!IsBaseOf<D, A>::value), "D is not a base of A"); static_assert((IsBaseOf<B, B>::value), "B is the same as B (and therefore, a base of B)"); } +class ExplicitCopyConstructor { + explicit ExplicitCopyConstructor(const ExplicitCopyConstructor&) = default; +}; + static void TestIsConvertible() { // Pointer type convertibility static_assert((IsConvertible<A*, A*>::value), "A* should convert to A*"); static_assert((IsConvertible<B*, A*>::value), "B* should convert to A*"); @@ -363,16 +367,20 @@ TestIsConvertible() "D and A are unrelated"); static_assert((!IsConvertible<A, D>::value), "A and D are unrelated"); static_assert(IsConvertible<void, void>::value, "void is void"); static_assert(!IsConvertible<A, void>::value, "A shouldn't convert to void"); static_assert(!IsConvertible<void, B>::value, "void shouldn't convert to B"); + static_assert(!IsConvertible<const ExplicitCopyConstructor&, + ExplicitCopyConstructor>::value, + "IsConvertible should test for implicit convertibility"); + // These cases seem to require C++11 support to properly implement them, so // for now just disable them. //static_assert((!IsConvertible<C*, A*>::value), // "C* shouldn't convert to A* (private inheritance)"); //static_assert((!IsConvertible<C, A>::value), // "C doesn't convert to A (private inheritance)"); }