LibreOffice Module vcl (master)  1
vclptr.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_VCL_PTR_HXX
21 #define INCLUDED_VCL_PTR_HXX
22 
23 #include <sal/config.h>
24 
25 #include <rtl/ref.hxx>
26 
27 #include <utility>
28 #include <type_traits>
29 
30 #ifdef DBG_UTIL
31 #ifndef WNT
32 #include <vcl/vclmain.hxx>
33 #endif
34 #endif
35 
36 class VclReferenceBase;
37 
38 namespace vcl { namespace detail {
39 
40 template<typename>
41 constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42 
43 template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44  int (*)[sizeof(T)])
45 { return std::is_base_of<VclReferenceBase, T>::value; }
46 
47 }; }; // namespace detail, namespace vcl
48 
56 template <class reference_type>
57 class VclPtr
58 {
59  static_assert(
60  vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61  nullptr),
62  "template argument type must be derived from VclReferenceBase");
63 
65 
66 public:
70  : m_rInnerRef()
71  {}
72 
75  VclPtr (reference_type * pBody)
76  : m_rInnerRef(pBody)
77  {}
78 
81  VclPtr (reference_type * pBody, __sal_NoAcquire)
82  : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83  {}
84 
93  template< class derived_type >
95  const VclPtr< derived_type > & rRef,
96  typename std::enable_if<
97  std::is_base_of<reference_type, derived_type>::value, int>::type
98  = 0 )
99  : m_rInnerRef( static_cast<reference_type*>(rRef) )
100  {
101  }
102 
103 #if defined(DBG_UTIL) && !defined(WNT)
104  virtual ~VclPtr()
105  {
106  assert(m_rInnerRef.get() == nullptr || vclmain::isAlive());
107  // We can be one of the intermediate counts, but if we are the last
108  // VclPtr keeping this object alive, then something forgot to call dispose().
109  assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)
110  && "someone forgot to call dispose()");
111  }
112  VclPtr(VclPtr const &) = default;
113  VclPtr(VclPtr &&) = default;
114  VclPtr & operator =(VclPtr const &) = default;
115  VclPtr & operator =(VclPtr &&) = default;
116 #endif
117 
127  template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128  {
129  return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130  }
131 
134  reference_type * operator->() const
135  {
136  return m_rInnerRef.get();
137  }
138 
143  reference_type * get() const
144  {
145  return m_rInnerRef.get();
146  }
147 
148  void set(reference_type *pBody)
149  {
150  m_rInnerRef.set(pBody);
151  }
152 
153  void reset(reference_type *pBody)
154  {
155  m_rInnerRef.set(pBody);
156  }
157 
164  template<typename derived_type>
165  typename std::enable_if<
166  std::is_base_of<reference_type, derived_type>::value,
167  VclPtr &>::type
169  {
170  m_rInnerRef.set(rRef.get());
171  return *this;
172  }
173 
174  VclPtr & operator =(reference_type * pBody)
175  {
176  m_rInnerRef.set(pBody);
177  return *this;
178  }
179 
180  operator reference_type * () const
181  {
182  return m_rInnerRef.get();
183  }
184 
185  explicit operator bool () const
186  {
187  return m_rInnerRef.get() != nullptr;
188  }
189 
190  void clear()
191  {
192  m_rInnerRef.clear();
193  }
194 
195  void reset()
196  {
197  m_rInnerRef.clear();
198  }
199 
201  {
202  // hold it alive for the lifetime of this method
203  ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204  m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
205  if (aTmp.get()) {
206  aTmp->disposeOnce();
207  }
208  }
209 
212  bool operator< (const VclPtr<reference_type> & handle) const
213  {
214  return (m_rInnerRef < handle.m_rInnerRef);
215  }
216 }; // class VclPtr
217 
218 template<typename T1, typename T2>
219 inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220  return p1.get() == p2.get();
221 }
222 
223 template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224 {
225  return p1.get() == p2;
226 }
227 
228 template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229  return p1.get() == p2;
230 }
231 
232 template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233 {
234  return p1 == p2.get();
235 }
236 
237 template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238  return p1 == p2.get();
239 }
240 
241 template<typename T1, typename T2>
242 inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243  return !(p1 == p2);
244 }
245 
246 template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247 {
248  return !(p1 == p2);
249 }
250 
251 template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252  return !(p1 == p2);
253 }
254 
255 template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256 {
257  return !(p1 == p2);
258 }
259 
260 template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261  return !(p1 == p2);
262 }
263 
274 template <class reference_type>
275 class SAL_WARN_UNUSED VclPtrInstance final : public VclPtr<reference_type>
276 {
277 public:
278  template<typename... Arg> VclPtrInstance(Arg &&... arg)
279  : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280  {
281  }
282 
287  template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288 };
289 
290 template <class reference_type>
291 class ScopedVclPtr : public VclPtr<reference_type>
292 {
293 public:
297  : VclPtr<reference_type>()
298  {}
299 
302  ScopedVclPtr (reference_type * pBody)
303  : VclPtr<reference_type>(pBody)
304  {}
305 
309  : VclPtr<reference_type>(handle)
310  {}
311 
315  void disposeAndReset(reference_type *pBody)
316  {
317  if (pBody != this->get()) {
320  }
321  }
322 
326  ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327  {
328  disposeAndReset(pBody);
329  return *this;
330  }
331 
340  template< class derived_type >
342  const VclPtr< derived_type > & rRef,
343  typename std::enable_if<
344  std::is_base_of<reference_type, derived_type>::value, int>::type
345  = 0 )
346  : VclPtr<reference_type>( rRef )
347  {
348  }
349 
356  template<typename derived_type>
357  typename std::enable_if<
358  std::is_base_of<reference_type, derived_type>::value,
359  ScopedVclPtr &>::type
361  {
362  disposeAndReset(rRef.get());
363  return *this;
364  }
365 
370  template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371 
373  {
375  assert(VclPtr<reference_type>::get() == nullptr); // make sure there are no lingering references
376  }
377 
378 private:
379  // Most likely we don't want this default copy-constructor.
380  ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381  // And certainly we don't want a default assignment operator.
383  // And disallow reset as that doesn't call disposeAndClear on the original reference
384  void reset() = delete;
385  void reset(reference_type *pBody) = delete;
386 
387 protected:
388  ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389  : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390  {}
391 };
392 
402 #if defined _MSC_VER
403 #pragma warning(push)
404 #pragma warning(disable: 4521) // " multiple copy constructors specified"
405 #endif
406 template <class reference_type>
407 class SAL_WARN_UNUSED ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408 {
409 public:
410  template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411  : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412  {
413  }
414 
419  template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420 
421 private:
422  // Prevent the above perfect forwarding ctor from hijacking (accidental)
423  // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424  // would typically lead to somewhat obscure error messages); both non-const
425  // and const variants are needed here, as the ScopedVclPtr base class has a
426  // const--variant copy ctor, so the implicitly declared copy ctor for
427  // ScopedVclPtrInstance would also be the const variant, so non-const copy
428  // construction attempts would be hijacked by the perfect forwarding ctor;
429  // but if we only declared a non-const variant here, the const variant would
430  // no longer be implicitly declared (as there would already be an explicitly
431  // declared copy ctor), so const copy construction attempts would then be
432  // hijacked by the perfect forwarding ctor:
434  ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435 };
436 #if defined _MSC_VER
437 #pragma warning(pop)
438 #endif
439 
440 #endif // INCLUDED_VCL_PTR_HXX
441 
442 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
VclPtrInstance(Arg &&...arg)
Definition: vclptr.hxx:278
ScopedVclPtr(reference_type *pBody)
Constructor.
Definition: vclptr.hxx:302
VclPtr & operator=(VclPtr const &)=default
static ScopedVclPtr< reference_type > Create(Arg &&...)=delete
Override and disallow this, to prevent people accidentally calling it and actually getting VclPtr::Cr...
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: button.hxx:32
virtual ~VclPtr()
Definition: vclptr.hxx:104
void disposeAndClear()
Definition: vclptr.hxx:200
ScopedVclPtr(const VclPtr< derived_type > &rRef, typename std::enable_if< std::is_base_of< reference_type, derived_type >::value, int >::type=0)
Up-casting conversion constructor: Copies interface reference.
Definition: vclptr.hxx:341
ScopedVclPtrInstance(Arg &&...arg)
Definition: vclptr.hxx:410
VclPtr(reference_type *pBody, __sal_NoAcquire)
Constructor...
Definition: vclptr.hxx:81
A construction helper for ScopedVclPtr.
Definition: vclptr.hxx:407
void disposeAndReset(reference_type *pBody)
Assignment that releases the last reference.
Definition: vclptr.hxx:315
VclPtr(reference_type *pBody)
Constructor...
Definition: vclptr.hxx:75
void reset()
Definition: vclptr.hxx:195
void clear()
Definition: vclptr.hxx:190
VclPtr(const VclPtr< derived_type > &rRef, typename std::enable_if< std::is_base_of< reference_type, derived_type >::value, int >::type=0)
Up-casting conversion constructor: Copies interface reference.
Definition: vclptr.hxx:94
bool operator==(VclPtr< T1 > const &p1, VclPtr< T2 > const &p2)
Definition: vclptr.hxx:219
VclPtr()
Constructor...
Definition: vclptr.hxx:69
reference_type * operator->() const
Probably most common used: handle->someBodyOp().
Definition: vclptr.hxx:134
ScopedVclPtr< reference_type > & operator=(reference_type *pBody)
Assignment that releases the last reference.
Definition: vclptr.hxx:326
ScopedVclPtr(reference_type *pBody, __sal_NoAcquire)
Definition: vclptr.hxx:388
void reset(reference_type *pBody)
Definition: vclptr.hxx:153
ScopedVclPtr()
Constructor...
Definition: vclptr.hxx:296
def forward(n)
#define SAL_WARN_UNUSED
A construction helper for a temporary VclPtr.
Definition: vclptr.hxx:275
::rtl::Reference< reference_type > m_rInnerRef
Definition: vclptr.hxx:62
bool operator!=(VclPtr< T1 > const &p1, VclPtr< T2 > const &p2)
Definition: vclptr.hxx:242
constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...)
Definition: vclptr.hxx:41
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
ScopedVclPtr(const VclPtr< reference_type > &handle)
Copy constructor...
Definition: vclptr.hxx:308
bool isAlive()
Definition: svmain.cxx:275
void set(reference_type *pBody)
Definition: vclptr.hxx:148
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
void reset()=delete