Lumiera  0.pre.03
»edit your freedom«
virtual-copy-support.hpp
Go to the documentation of this file.
1 /*
2  VIRTUAL-COPY-SUPPORT.hpp - helper to support copying of erased sub-types
3 
4  Copyright (C) Lumiera.org
5  2015, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
114 #ifndef LIB_META_VIRTUAL_COPY_SUPPORT_H
115 #define LIB_META_VIRTUAL_COPY_SUPPORT_H
116 
117 
118 #include "lib/error.hpp"
119 
120 #include <type_traits>
121 #include <utility>
122 
123 
124 namespace lib {
125 namespace meta{
126 
127  using std::move;
128 
129  using std::is_move_constructible;
130  using std::is_copy_constructible;
131  using std::is_copy_assignable;
132  using std::__and_;
133  using std::__not_;
134 
135  namespace error = lumiera::error;
136 
137 
138 
139  struct EmptyBase { };
140 
141  template<class IFA, class BASE = EmptyBase>
143  : public BASE
144  {
145  public:
146  virtual ~VirtualCopySupportInterface() { }
147 
148  virtual void copyInto (void* targetStorage) const =0;
149  virtual void moveInto (void* targetStorage) =0;
150  virtual void copyInto (IFA& target) const =0;
151  virtual void moveInto (IFA& target) =0;
152  };
153 
154 
155 
156  template<class I, class D, class B =I>
158  : public B
159  {
160  virtual void
161  copyInto (void*) const override
162  {
163  throw error::Logic{"Copy construction invoked but target is noncopyable"};
164  }
165 
166  virtual void
167  moveInto (void*) override
168  {
169  throw error::Logic{"Move construction invoked but target is noncopyable"};
170  }
171 
172  virtual void
173  copyInto (I&) const override
174  {
175  throw error::Logic{"Assignment invoked but target is not assignable"};
176  }
177 
178  virtual void
179  moveInto (I&) override
180  {
181  throw error::Logic{"Assignment invoked but target is not assignable"};
182  }
183  };
184 
185 
186  template<class I, class D, class B =I>
188  : public NoCopyMoveSupport<I,D,B>
189  {
190  virtual void
191  copyInto (void*) const override
192  {
193  throw error::Logic{"Copy construction invoked but target allows only move construction"};
194  }
195 
196  virtual void
197  moveInto (void* targetStorage) override
198  {
199  D& src = static_cast<D&> (*this);
200  new(targetStorage) D(move(src));
201  }
202  };
203 
204 
205  template<class I, class D, class B =I>
207  : public MoveSupport<I,D,B>
208  {
209  virtual void
210  copyInto (void* targetStorage) const override
211  {
212  D const& src = static_cast<D const&> (*this);
213  new(targetStorage) D(src);
214  }
215  };
216 
217 
218  template<class I, class D, class B =I>
220  : public CloneSupport<I,D,B>
221  {
222  virtual void
223  copyInto (I& target) const override
224  {
225  D& t = D::downcast(target);
226  D const& s = static_cast<D const&> (*this);
227  t = s;
228  }
229 
230  virtual void
231  moveInto (I& target) override
232  {
233  D& t = D::downcast(target);
234  D& s = static_cast<D&> (*this);
235  t = move(s);
236  }
237  };
238 
239 
240 
241 
242  namespace { // helpers to select suitable variant of copy support...
243 
244  template<class X>
246  : __and_<is_move_constructible<X>
247  ,__not_<is_copy_constructible<X>>
248  ,__not_<is_copy_assignable<X>>
249  >
250  { };
251 
252  template<class X>
254  : __and_<is_move_constructible<X>
255  ,is_copy_constructible<X>
256  ,__not_<is_copy_assignable<X>>
257  >
258  { };
259 
260  template<class X>
262  : __and_<is_move_constructible<X>
263  ,is_copy_constructible<X>
264  ,is_copy_assignable<X>
265  >
266  { };
267  }
268 
269 
270 
271 
275  template<class X, class SEL=void>
276  struct CopySupport
277  {
278  template<class I, class D, class B =I>
280  };
281 
282  template<class X>
283  struct CopySupport<X, enable_if<supports_only_move<X>> >
284  {
285  template<class I, class D, class B =I>
286  using Policy = MoveSupport<I,D,B>;
287  };
288 
289  template<class X>
290  struct CopySupport<X, enable_if<supports_cloning<X>> >
291  {
292  template<class I, class D, class B =I>
293  using Policy = CloneSupport<I,D,B>;
294  };
295 
296  template<class X>
297  struct CopySupport<X, enable_if<supports_copy_and_assignment<X>> >
298  {
299  template<class I, class D, class B =I>
301  };
302 
303 
304 
305 
306 }} // namespace lib::meta
307 #endif /*LIB_META_VIRTUAL_COPY_SUPPORT_H*/
Policy to pick a suitable implementation of "virtual copy operations".
Implementation namespace for support and library code.
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:92
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Lumiera error handling (C++ interface).