Bug 819523 part 1. Make it possible to use the various-allocator nsTArrays interchangeably as long as you're working with const objects. r=jlebar
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 18 Dec 2012 20:16:05 -0500
changeset 125576 6ed3f784cdd31e08f0488663d3bc533535802b5a
parent 125575 b6e9ba8a6a207522c39c539af5453d2db8ad2644
child 125577 51e3f82d820bf71d316470de9ffd8de92f8f0b09
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlebar
bugs819523
milestone20.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 819523 part 1. Make it possible to use the various-allocator nsTArrays interchangeably as long as you're working with const objects. r=jlebar
xpcom/glue/nsTArray.h
xpcom/tests/TestTArray.cpp
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -369,16 +369,19 @@ public:
   bool Equals(const A& a, const B& b) const {
     return a == b;
   }
   bool LessThan(const A& a, const B& b) const {
     return a < b;
   }
 };
 
+template <class E> class InfallibleTArray;
+template <class E> class FallibleTArray;
+
 //
 // The templatized array class that dynamically resizes its storage as
 // elements are added.  This class is designed to behave a bit like
 // std::vector, though note that unlike std::vector, nsTArray doesn't
 // follow C++ construction/destruction rules.
 //
 // The template parameter specifies the type of the elements (elem_type), and
 // has the following requirements:
@@ -458,16 +461,30 @@ public:
     AppendElements(other);
   }
 
   template<typename Allocator>
   explicit nsTArray(const nsTArray<E, Allocator>& other) {
     AppendElements(other);
   }
 
+  // Allow converting to a const array with a different kind of allocator,
+  // Since the allocator doesn't matter for const arrays
+  template<typename Allocator>
+  operator const nsTArray<E, Allocator>&() const {
+    return *reinterpret_cast<const nsTArray<E, Allocator>*>(this);
+  }
+  // And we have to do this for our subclasses too
+  operator const InfallibleTArray<E>&() const {
+    return *reinterpret_cast<const InfallibleTArray<E>*>(this);
+  }
+  operator const FallibleTArray<E>&() const {
+    return *reinterpret_cast<const FallibleTArray<E>*>(this);
+  }
+
   // The array's assignment operator performs a 'deep' copy of the given
   // array.  It is optimized to reuse existing storage if possible.
   // @param other  The array object to copy.
   nsTArray& operator=(const self_type& other) {
     ReplaceElementsAt(0, Length(), other.Elements(), other.Length());
     return *this;
   }
 
--- a/xpcom/tests/TestTArray.cpp
+++ b/xpcom/tests/TestTArray.cpp
@@ -866,16 +866,69 @@ static bool test_fallible()
   }
 
   // No OOM?  That's...weird.
   printf("test_fallible: Didn't OOM or crash?  nsTArray::SetCapacity "
          "must be lying.\n");
   return false;
 }
 
+static bool test_conversion_operator() {
+  FallibleTArray<int> f;
+  const FallibleTArray<int> fconst;
+  AutoFallibleTArray<int, 8> fauto;
+  const AutoFallibleTArray<int, 8> fautoconst;
+
+  InfallibleTArray<int> i;
+  const InfallibleTArray<int> iconst;
+  AutoInfallibleTArray<int, 8> iauto;
+  const AutoInfallibleTArray<int, 8> iautoconst;
+
+  nsTArray<int> t;
+  const nsTArray<int> tconst;
+  nsAutoTArray<int, 8> tauto;
+  const nsAutoTArray<int, 8> tautoconst;
+
+#define CHECK_ARRAY_CAST(type)                                 \
+  do {                                                         \
+    const type<int>& z1 = f;                                   \
+    if ((void*)&z1 != (void*)&f) return false;                 \
+    const type<int>& z2 = fconst;                              \
+    if ((void*)&z2 != (void*)&fconst) return false;            \
+    const type<int>& z3 = fauto;                               \
+    if ((void*)&z3 != (void*)&fauto) return false;             \
+    const type<int>& z4 = fautoconst;                          \
+    if ((void*)&z4 != (void*)&fautoconst) return false;        \
+    const type<int>& z5 = i;                                   \
+    if ((void*)&z5 != (void*)&i) return false;                 \
+    const type<int>& z6 = iconst;                              \
+    if ((void*)&z6 != (void*)&iconst) return false;            \
+    const type<int>& z7 = iauto;                               \
+    if ((void*)&z7 != (void*)&iauto) return false;             \
+    const type<int>& z8 = iautoconst;                          \
+    if ((void*)&z8 != (void*)&iautoconst) return false;        \
+    const type<int>& z9 = t;                                   \
+    if ((void*)&z9 != (void*)&t) return false;                 \
+    const type<int>& z10 = tconst;                             \
+    if ((void*)&z10 != (void*)&tconst) return false;           \
+    const type<int>& z11 = tauto;                              \
+    if ((void*)&z11 != (void*)&tauto) return false;            \
+    const type<int>& z12 = tautoconst;                         \
+    if ((void*)&z12 != (void*)&tautoconst) return false;       \
+  } while (0)
+
+  CHECK_ARRAY_CAST(FallibleTArray);
+  CHECK_ARRAY_CAST(InfallibleTArray);
+  CHECK_ARRAY_CAST(nsTArray);
+
+#undef CHECK_ARRAY_CAST
+
+  return true;
+}
+
 //----
 
 typedef bool (*TestFunc)();
 #define DECL_TEST(name) { #name, name }
 
 static const struct Test {
   const char* name;
   TestFunc    func;
@@ -891,16 +944,17 @@ static const struct Test {
   DECL_TEST(test_ptrarray),
 #ifdef DEBUG
   DECL_TEST(test_autoarray),
 #endif
   DECL_TEST(test_indexof),
   DECL_TEST(test_heap),
   DECL_TEST(test_swap),
   DECL_TEST(test_fallible),
+  DECL_TEST(test_conversion_operator),
   { nullptr, nullptr }
 };
 
 }
 
 using namespace TestTArray;
 
 int main(int argc, char **argv) {