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 /*
8  * Provides DebugOnly, a type for variables used only in debug builds (i.e. by
9  * assertions).
10  */
11 
12 #ifndef mozilla_DebugOnly_h
13 #define mozilla_DebugOnly_h
14 
15 #include "mozilla/Attributes.h"
16 
17 namespace mozilla {
18 
19 /**
20  * DebugOnly contains a value of type T, but only in debug builds.  In release
21  * builds, it does not contain a value.  This helper is intended to be used with
22  * MOZ_ASSERT()-style macros, allowing one to write:
23  *
24  *   DebugOnly<bool> check = func();
25  *   MOZ_ASSERT(check);
26  *
27  * more concisely than declaring |check| conditional on #ifdef DEBUG, but also
28  * without allocating storage space for |check| in release builds.
29  *
30  * DebugOnly instances can only be coerced to T in debug builds.  In release
31  * builds they don't have a value, so type coercion is not well defined.
32  *
33  * Note that DebugOnly instances still take up one byte of space, plus padding,
34  * when used as members of structs.
35  */
36 template<typename T>
37 class DebugOnly
38 {
39 public:
40 #ifdef DEBUG
41   T value;
42 
DebugOnly()43   DebugOnly() { }
DebugOnly(const T & aOther)44   MOZ_IMPLICIT DebugOnly(const T& aOther) : value(aOther) { }
DebugOnly(const DebugOnly & aOther)45   DebugOnly(const DebugOnly& aOther) : value(aOther.value) { }
46   DebugOnly& operator=(const T& aRhs) {
47     value = aRhs;
48     return *this;
49   }
50 
51   void operator++(int) { value++; }
52   void operator--(int) { value--; }
53 
54   // Do not define operator+=(), etc. here.  These will coerce via the
55   // implicit cast and built-in operators.  Defining explicit methods here
56   // will create ambiguity the compiler can't deal with.
57 
58   T* operator&() { return &value; }
59 
60   operator T&() { return value; }
61   operator const T&() const { return value; }
62 
63   T& operator->() { return value; }
64   const T& operator->() const { return value; }
65 
66 #else
67   DebugOnly() { }
68   MOZ_IMPLICIT DebugOnly(const T&) { }
69   DebugOnly(const DebugOnly&) { }
70   DebugOnly& operator=(const T&) { return *this; }
71   void operator++(int) { }
72   void operator--(int) { }
73   DebugOnly& operator+=(const T&) { return *this; }
74   DebugOnly& operator-=(const T&) { return *this; }
75   DebugOnly& operator&=(const T&) { return *this; }
76   DebugOnly& operator|=(const T&) { return *this; }
77   DebugOnly& operator^=(const T&) { return *this; }
78 #endif
79 
80   /*
81    * DebugOnly must always have a destructor or else it will
82    * generate "unused variable" warnings, exactly what it's intended
83    * to avoid!
84    */
~DebugOnly()85   ~DebugOnly() {}
86 };
87 
88 } // namespace mozilla
89 
90 #endif /* mozilla_DebugOnly_h */
91