PImpl.hpp
Go to the documentation of this file.
1 //
3 // Aurora C++ Library
4 // Copyright (c) 2012-2016 Jan Haller
5 //
6 // This software is provided 'as-is', without any express or implied
7 // warranty. In no event will the authors be held liable for any damages
8 // arising from the use of this software.
9 //
10 // Permission is granted to anyone to use this software for any purpose,
11 // including commercial applications, and to alter it and redistribute it
12 // freely, subject to the following restrictions:
13 //
14 // 1. The origin of this software must not be misrepresented; you must not
15 // claim that you wrote the original software. If you use this software
16 // in a product, an acknowledgment in the product documentation would be
17 // appreciated but is not required.
18 //
19 // 2. Altered source versions must be plainly marked as such, and must not be
20 // misrepresented as being the original software.
21 //
22 // 3. This notice may not be removed or altered from any source distribution.
23 //
25 
28 
29 #ifndef AURORA_PIMPL_HPP
30 #define AURORA_PIMPL_HPP
31 
32 #include <Aurora/Config.hpp>
33 #include <Aurora/Tools/Swap.hpp>
34 
35 #include <type_traits> // std::aligned_storage
36 
37 
38 namespace aurora
39 {
40 
43 
68 template <typename T, std::size_t Size, std::size_t Align>
69 class PImpl
70 {
71  // ---------------------------------------------------------------------------------------------------------------------------
72  // Public member functions
73  public:
76  template <typename... Args>
77  explicit PImpl(Args&&... args)
78  {
79  check();
80  new (storage()) T(std::forward<Args>(args)...);
81  }
82 
85  PImpl(const PImpl& origin)
86  {
87  check();
88  new (storage()) T(*origin.storage());
89  }
90 
93  PImpl(PImpl&& source)
94  {
95  check();
96  new (storage()) T(std::move(*source.storage()));
97  }
98 
101  PImpl& operator= (const PImpl& origin)
102  {
103  PImpl(origin).swap(*this);
104  return *this;
105  }
106 
109  PImpl& operator= (PImpl&& source)
110  {
111  PImpl(std::move(source)).swap(*this);
112  return *this;
113  }
114 
118  {
119  storage()->~T();
120  }
121 
124  void swap(PImpl& other)
125  {
126  adlSwap(*storage(), *other.storage());
127  }
128 
132  {
133  return *storage();
134  }
135 
138  const T& operator* () const
139  {
140  return *storage();
141  }
142 
146  {
147  return storage();
148  }
149 
152  const T* operator-> () const
153  {
154  return storage();
155  }
156 
157 
158  // ---------------------------------------------------------------------------------------------------------------------------
159  // Private member functions
160  private:
161  T* storage()
162  {
163  return reinterpret_cast<T*>(&mStorage);
164  }
165 
166  const T* storage() const
167  {
168  return reinterpret_cast<const T*>(&mStorage);
169  }
170 
171  void check()
172  {
173  correctSizeAndAlignWouldBe<sizeof(T), std::alignment_of<T>::value>();
174  }
175 
176  template <std::size_t ActualSize, std::size_t ActualAlign>
177  void correctSizeAndAlignWouldBe()
178  {
179  static_assert(ActualSize <= Size, "PImpl: Size too small to hold type T");
180  static_assert(ActualAlign == Align, "PImpl: Alignment mismatch for type T");
181  }
182 
183 
184  // ---------------------------------------------------------------------------------------------------------------------------
185  // Private variables
186  private:
187  typename std::aligned_storage<Size, Align>::type mStorage;
188 };
189 
192 template <typename T, std::size_t Size, std::size_t Align>
194 {
195  lhs.swap(rhs);
196 }
197 
199 
200 } // namespace aurora
201 
202 #endif // AURORA_PIMPL_HPP
Fast PImpl idiom.
Definition: PImpl.hpp:69
void swap(PImpl< T, Size, Align > &lhs, PImpl< T, Size, Align > &rhs)
Swaps two implementation objects.
Definition: PImpl.hpp:193
Configuration header of the library.
T * operator->()
Returns the implementation object for member access.
Definition: PImpl.hpp:145
~PImpl()
Destructor.
Definition: PImpl.hpp:117
void swap(PImpl &other)
Swaps two implementation objects.
Definition: PImpl.hpp:124
Helpers to declare and invoke swap() functions.
T & operator*()
Returns the implementation object.
Definition: PImpl.hpp:131
PImpl(PImpl &&source)
Move constructor.
Definition: PImpl.hpp:93
PImpl & operator=(const PImpl &origin)
Copy assignment operator.
Definition: PImpl.hpp:101
PImpl(Args &&...args)
Construct implementation object, forwarding arguments.
Definition: PImpl.hpp:77
void adlSwap(T &lhs, T &rhs)
swap() function with argument-dependent lookup
Definition: Swap.hpp:49
PImpl(const PImpl &origin)
Copy constructor.
Definition: PImpl.hpp:85
Definition: DispatchTraits.hpp:39