DocWire SDK
DocWire SDK: Award-winning modern data processing in C++20. SourceForge Community Choice & Microsoft support. AI-driven processing. Supports nearly 100 data formats, including email boxes and OCR. Boost efficiency in text extraction, web data extraction, data mining, document analysis. Offline processing possible for security and confidentiality
pimpl.h
1 /*********************************************************************************************************************************************/
2 /* DocWire SDK: Award-winning modern data processing in C++20. SourceForge Community Choice & Microsoft support. AI-driven processing. */
3 /* Supports nearly 100 data formats, including email boxes and OCR. Boost efficiency in text extraction, web data extraction, data mining, */
4 /* document analysis. Offline processing possible for security and confidentiality */
5 /* */
6 /* Copyright (c) SILVERCODERS Ltd, http://silvercoders.com */
7 /* Project homepage: https://github.com/docwire/docwire */
8 /* */
9 /* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-DocWire-Commercial */
10 /*********************************************************************************************************************************************/
11 
12 #ifndef DOCWIRE_PIMPL_H
13 #define DOCWIRE_PIMPL_H
14 
15 #include <memory>
16 
17 namespace docwire
18 {
19 
20 template <typename T>
21 struct pimpl_impl;
22 
23 class with_pimpl_base {};
24 
26 {
27  virtual ~pimpl_impl_base() = default;
28  virtual void set_owner(with_pimpl_base&)
29  {
30  }
31 };
32 
33 template <typename T>
34 class with_pimpl_owner;
35 
36 template <typename T>
38 {
39 protected:
40  using impl_type = pimpl_impl<T>;
41 
42  template <typename... Args>
43  impl_type* create_impl(Args&&... args)
44  {
45  if constexpr (std::is_base_of_v<with_pimpl_owner<T>, impl_type>)
46  {
47  static_assert(std::is_constructible_v<impl_type, T&, Args...>,
48  "Template specialization of pimpl_impl<T> that inherits from with_pimpl_owner<T> is required to have constructor with T&, Args... arguments");
49  return new impl_type(static_cast<T&>(*this), std::forward<Args>(args)...);
50  }
51  else
52  {
53  static_assert(std::is_constructible_v<impl_type, Args...>,
54  "Template specialization of pimpl_impl<T> is required to have constructor with Args... arguments");
55  return new impl_type(std::forward<Args>(args)...);
56  }
57  }
58 
59  template <typename... Args>
60  explicit with_pimpl(Args&&... args)
61  : m_impl(static_cast<pimpl_impl_base*>(create_impl(std::forward<Args>(args)...)))
62  {
63  }
64 
65  with_pimpl(with_pimpl<T>&& other) noexcept
66  : m_impl(std::move(other.m_impl))
67  {
68  if (m_impl)
69  set_impl_owner();
70  }
71 
72  with_pimpl(std::nullptr_t) {}
73 
74  with_pimpl& operator=(with_pimpl&& other) noexcept {
75  if (this != &other)
76  {
77  m_impl = std::move(other.m_impl);
78  if (m_impl)
79  set_impl_owner();
80  }
81  return *this;
82  }
83 
84  template <typename DeferInstantiation = void>
85  impl_type& impl() { return *static_cast<impl_type*>(m_impl.get()); }
86 
87  template <typename DeferInstantiation = void>
88  const impl_type& impl() const { return *static_cast<impl_type*>(m_impl.get()); }
89 
90 private:
91  std::unique_ptr<pimpl_impl_base> m_impl;
92 
93  void set_impl_owner()
94  {
95  m_impl->set_owner(*this);
96  }
97 };
98 
99 template <typename T>
101 {
102 protected:
103  with_pimpl_owner(T& owner) : m_owner(owner) {}
104  T& owner() { return m_owner; }
105  const T& owner() const { return m_owner; }
106 
107  void set_owner(with_pimpl_base& owner) override
108  {
109  m_owner = static_cast<T&>(static_cast<with_pimpl<T>&>(owner));
110  }
111 
112 private:
113  std::reference_wrapper<T> m_owner;
114  friend with_pimpl<T>;
115 };
116 
117 } // namespace docwire
118 
119 #endif
The main namespace for the DocWire SDK.
Definition: ai_elements.h:19