LCOV - code coverage report
Current view: top level - mfbt - Pair.h (source / functions) Hit Total Coverage
Test: output.info Lines: 21 31 67.7 %
Date: 2017-07-14 16:53:18 Functions: 821 4337 18.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* A class holding a pair of objects that tries to conserve storage space. */
       8             : 
       9             : #ifndef mozilla_Pair_h
      10             : #define mozilla_Pair_h
      11             : 
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/Move.h"
      14             : #include "mozilla/TypeTraits.h"
      15             : 
      16             : namespace mozilla {
      17             : 
      18             : namespace detail {
      19             : 
      20             : enum StorageType { AsBase, AsMember };
      21             : 
      22             : // Optimize storage using the Empty Base Optimization -- that empty base classes
      23             : // don't take up space -- to optimize size when one or the other class is
      24             : // stateless and can be used as a base class.
      25             : //
      26             : // The extra conditions on storage for B are necessary so that PairHelper won't
      27             : // ambiguously inherit from either A or B, such that one or the other base class
      28             : // would be inaccessible.
      29             : template<typename A, typename B,
      30             :          detail::StorageType =
      31             :            IsEmpty<A>::value ? detail::AsBase : detail::AsMember,
      32             :          detail::StorageType =
      33             :            IsEmpty<B>::value && !IsBaseOf<A, B>::value && !IsBaseOf<B, A>::value
      34             :            ? detail::AsBase
      35             :            : detail::AsMember>
      36             : struct PairHelper;
      37             : 
      38             : template<typename A, typename B>
      39          24 : struct PairHelper<A, B, AsMember, AsMember>
      40             : {
      41             : protected:
      42             :   template<typename AArg, typename BArg>
      43         651 :   PairHelper(AArg&& aA, BArg&& aB)
      44         627 :     : mFirstA(Forward<AArg>(aA)),
      45         651 :       mSecondB(Forward<BArg>(aB))
      46         651 :   {}
      47             : 
      48        2532 :   A& first() { return mFirstA; }
      49       51987 :   const A& first() const { return mFirstA; }
      50          24 :   B& second() { return mSecondB; }
      51           0 :   const B& second() const { return mSecondB; }
      52             : 
      53             :   void swap(PairHelper& aOther)
      54             :   {
      55             :     Swap(mFirstA, aOther.mFirstA);
      56             :     Swap(mSecondB, aOther.mSecondB);
      57             :   }
      58             : 
      59             : private:
      60             :   A mFirstA;
      61             :   B mSecondB;
      62             : };
      63             : 
      64             : template<typename A, typename B>
      65             : struct PairHelper<A, B, AsMember, AsBase> : private B
      66             : {
      67             : protected:
      68             :   template<typename AArg, typename BArg>
      69      340173 :   PairHelper(AArg&& aA, BArg&& aB)
      70      340173 :     : B(Forward<BArg>(aB)),
      71      340172 :       mFirstA(Forward<AArg>(aA))
      72      340172 :   {}
      73             : 
      74      999907 :   A& first() { return mFirstA; }
      75      486541 :   const A& first() const { return mFirstA; }
      76      119536 :   B& second() { return *this; }
      77             :   const B& second() const { return *this; }
      78             : 
      79           0 :   void swap(PairHelper& aOther)
      80             :   {
      81           0 :     Swap(mFirstA, aOther.mFirstA);
      82           0 :     Swap(static_cast<B&>(*this), static_cast<B&>(aOther));
      83           0 :   }
      84             : 
      85             : private:
      86             :   A mFirstA;
      87             : };
      88             : 
      89             : template<typename A, typename B>
      90             : struct PairHelper<A, B, AsBase, AsMember> : private A
      91             : {
      92             : protected:
      93             :   template<typename AArg, typename BArg>
      94             :   PairHelper(AArg&& aA, BArg&& aB)
      95             :     : A(Forward<AArg>(aA)),
      96             :       mSecondB(Forward<BArg>(aB))
      97             :   {}
      98             : 
      99             :   A& first() { return *this; }
     100             :   const A& first() const { return *this; }
     101             :   B& second() { return mSecondB; }
     102             :   const B& second() const { return mSecondB; }
     103             : 
     104             :   void swap(PairHelper& aOther)
     105             :   {
     106             :     Swap(static_cast<A&>(*this), static_cast<A&>(aOther));
     107             :     Swap(mSecondB, aOther.mSecondB);
     108             :   }
     109             : 
     110             : private:
     111             :   B mSecondB;
     112             : };
     113             : 
     114             : template<typename A, typename B>
     115             : struct PairHelper<A, B, AsBase, AsBase> : private A, private B
     116             : {
     117             : protected:
     118             :   template<typename AArg, typename BArg>
     119             :   PairHelper(AArg&& aA, BArg&& aB)
     120             :     : A(Forward<AArg>(aA)),
     121             :       B(Forward<BArg>(aB))
     122             :   {}
     123             : 
     124             :   A& first() { return static_cast<A&>(*this); }
     125             :   const A& first() const { return static_cast<A&>(*this); }
     126             :   B& second() { return static_cast<B&>(*this); }
     127             :   const B& second() const { return static_cast<B&>(*this); }
     128             : 
     129             :   void swap(PairHelper& aOther)
     130             :   {
     131             :     Swap(static_cast<A&>(*this), static_cast<A&>(aOther));
     132             :     Swap(static_cast<B&>(*this), static_cast<B&>(aOther));
     133             :   }
     134             : };
     135             : 
     136             : } // namespace detail
     137             : 
     138             : /**
     139             :  * Pair is the logical concatenation of an instance of A with an instance B.
     140             :  * Space is conserved when possible.  Neither A nor B may be a final class.
     141             :  *
     142             :  * It's typically clearer to have individual A and B member fields.  Except if
     143             :  * you want the space-conserving qualities of Pair, you're probably better off
     144             :  * not using this!
     145             :  *
     146             :  * No guarantees are provided about the memory layout of A and B, the order of
     147             :  * initialization or destruction of A and B, and so on.  (This is approximately
     148             :  * required to optimize space usage.)  The first/second names are merely
     149             :  * conceptual!
     150             :  */
     151             : template<typename A, typename B>
     152          24 : struct Pair
     153             :   : private detail::PairHelper<A, B>
     154             : {
     155             :   typedef typename detail::PairHelper<A, B> Base;
     156             : 
     157             : public:
     158             :   template<typename AArg, typename BArg>
     159      340821 :   Pair(AArg&& aA, BArg&& aB)
     160      340821 :     : Base(Forward<AArg>(aA), Forward<BArg>(aB))
     161      340820 :   {}
     162             : 
     163           0 :   Pair(Pair&& aOther)
     164           0 :     : Base(Move(aOther.first()), Move(aOther.second()))
     165           0 :   { }
     166             : 
     167           0 :   Pair(const Pair& aOther) = default;
     168             : 
     169             :   Pair& operator=(Pair&& aOther)
     170             :   {
     171             :     MOZ_ASSERT(this != &aOther, "Self-moves are prohibited");
     172             : 
     173             :     first() = Move(aOther.first());
     174             :     second() = Move(aOther.second());
     175             : 
     176             :     return *this;
     177             :   }
     178             : 
     179             :   Pair& operator=(const Pair& aOther) = default;
     180             : 
     181             :   /** The A instance. */
     182             :   using Base::first;
     183             :   /** The B instance. */
     184             :   using Base::second;
     185             : 
     186             :   /** Swap this pair with another pair. */
     187           0 :   void swap(Pair& aOther) { Base::swap(aOther); }
     188             : };
     189             : 
     190             : template<typename A, class B>
     191             : void
     192             : Swap(Pair<A, B>& aX, Pair<A, B>& aY)
     193             : {
     194             :   aX.swap(aY);
     195             : }
     196             : 
     197             : /**
     198             :  * MakePair allows you to construct a Pair instance using type inference. A call
     199             :  * like this:
     200             :  *
     201             :  *   MakePair(Foo(), Bar())
     202             :  *
     203             :  * will return a Pair<Foo, Bar>.
     204             :  */
     205             : template<typename A, typename B>
     206             : Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
     207             :      typename RemoveCV<typename RemoveReference<B>::Type>::Type>
     208          24 : MakePair(A&& aA, B&& aB)
     209             : {
     210             :   return
     211             :     Pair<typename RemoveCV<typename RemoveReference<A>::Type>::Type,
     212             :          typename RemoveCV<typename RemoveReference<B>::Type>::Type>(
     213             :              Forward<A>(aA),
     214          24 :              Forward<B>(aB));
     215             : }
     216             : 
     217             : } // namespace mozilla
     218             : 
     219             : #endif /* mozilla_Pair_h */

Generated by: LCOV version 1.13