Bug 1153295 - Add mozilla::Declval. r=nfroyd
authorGerald Squelart <from_mozilla@squelart.com>
Mon, 27 Apr 2015 18:11:00 -0400
changeset 275048 33e0c218bdd599d7458016aff94f47921611a052
parent 275047 51e154ebe5238ed06ab75ced6253bfb67f8906dd
child 275049 090bfb8d6e9ae938e74e3e08ebd9f7dbd2bf2f1c
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs1153295
milestone41.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
Bug 1153295 - Add mozilla::Declval. r=nfroyd
mfbt/TypeTraits.h
mfbt/tests/TestTypeTraits.cpp
xpcom/glue/nsISupportsImpl.h
--- a/mfbt/TypeTraits.h
+++ b/mfbt/TypeTraits.h
@@ -806,16 +806,27 @@ 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
@@ -4,16 +4,17 @@
  * 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"
 
 using mozilla::AddLvalueReference;
 using mozilla::AddRvalueReference;
+using mozilla::DeclVal;
 using mozilla::IsArray;
 using mozilla::IsBaseOf;
 using mozilla::IsClass;
 using mozilla::IsConvertible;
 using mozilla::IsEmpty;
 using mozilla::IsLvalueReference;
 using mozilla::IsPointer;
 using mozilla::IsReference;
@@ -380,16 +381,33 @@ static_assert(IsSame<AddRvalueReference<
               "not adding && to volatile int& correctly");
 static_assert(IsSame<AddRvalueReference<void*>::Type, void*&&>::value,
               "not adding && to void* correctly");
 static_assert(IsSame<AddRvalueReference<void>::Type, void>::value,
               "void shouldn't be transformed by AddRvalueReference");
 static_assert(IsSame<AddRvalueReference<struct S1&>::Type, struct S1&>::value,
               "not reference-collapsing struct S1& && to struct S1& correctly");
 
+struct TestWithDefaultConstructor
+{
+  int foo() const { return 0; }
+};
+struct TestWithNoDefaultConstructor
+{
+  explicit TestWithNoDefaultConstructor(int) {}
+  int foo() const { return 1; }
+};
+
+static_assert(IsSame<decltype(TestWithDefaultConstructor().foo()), int>::value,
+              "decltype should work using a struct with a default constructor");
+static_assert(IsSame<decltype(DeclVal<TestWithDefaultConstructor>().foo()), int>::value,
+              "decltype should work using a DeclVal'd struct with a default constructor");
+static_assert(IsSame<decltype(DeclVal<TestWithNoDefaultConstructor>().foo()), int>::value,
+              "decltype should work using a DeclVal'd struct without a default constructor");
+
 static_assert(IsSame<MakeSigned<const unsigned char>::Type, const signed char>::value,
               "const unsigned char won't signify correctly");
 static_assert(IsSame<MakeSigned<volatile unsigned short>::Type, volatile signed short>::value,
               "volatile unsigned short won't signify correctly");
 static_assert(IsSame<MakeSigned<const volatile unsigned int>::Type, const volatile signed int>::value,
               "const volatile unsigned int won't signify correctly");
 static_assert(IsSame<MakeSigned<unsigned long>::Type, signed long>::value,
               "unsigned long won't signify correctly");
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -24,16 +24,17 @@
 #include "mozilla/Atomics.h"
 #endif
 #include "mozilla/Attributes.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Compiler.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MacroArgs.h"
 #include "mozilla/MacroForEach.h"
+#include "mozilla/TypeTraits.h"
 
 namespace mozilla {
 template <typename T>
 struct HasDangerousPublicDestructor
 {
   static const bool value = false;
 };
 }
@@ -57,19 +58,17 @@ struct HasDangerousPublicDestructor
 
 #ifdef MOZ_HAVE_STD_IS_DESTRUCTIBLE
 #  include <type_traits>
 #  define MOZ_IS_DESTRUCTIBLE(X) (std::is_destructible<X>::value)
 #elif defined MOZ_CAN_USE_IS_DESTRUCTIBLE_FALLBACK
   namespace mozilla {
     struct IsDestructibleFallbackImpl
     {
-      template<typename T> static T&& Declval();
-
-      template<typename T, typename = decltype(Declval<T>().~T())>
+      template<typename T, typename = decltype(DeclVal<T>().~T())>
       static TrueType Test(int);
 
       template<typename>
       static FalseType Test(...);
 
       template<typename T>
       struct Selector
       {