Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
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)
5 2015, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
105#ifndef LIB_META_VIRTUAL_COPY_SUPPORT_H
106#define LIB_META_VIRTUAL_COPY_SUPPORT_H
107
108
109#include "lib/error.hpp"
110
111#include <type_traits>
112#include <utility>
113
114
115namespace lib {
116namespace meta{
117
118 using std::move;
119
120 using std::is_move_constructible;
121 using std::is_copy_constructible;
122 using std::is_copy_assignable;
123 using std::__and_;
124 using std::__not_;
125
126 namespace error = lumiera::error;
127
128
129
130 struct EmptyBase { };
131
132 template<class IFA, class BASE = EmptyBase>
134 : public BASE
135 {
136 public:
138
139 virtual void copyInto (void* targetStorage) const =0;
140 virtual void moveInto (void* targetStorage) =0;
141 virtual void copyInto (IFA& target) const =0;
142 virtual void moveInto (IFA& target) =0;
143 };
144
145
146
147 template<class I, class D, class B =I>
149 : public B
150 {
151 public:
152 virtual void
153 copyInto (void*) const override
154 {
155 throw error::Logic{"Copy construction invoked but target is noncopyable"};
156 }
157
158 virtual void
159 moveInto (void*) override
160 {
161 throw error::Logic{"Move construction invoked but target is noncopyable"};
162 }
163
164 virtual void
165 copyInto (I&) const override
166 {
167 throw error::Logic{"Assignment invoked but target is not assignable"};
168 }
169
170 virtual void
171 moveInto (I&) override
172 {
173 throw error::Logic{"Assignment invoked but target is not assignable"};
174 }
175 };
176
177
178 template<class I, class D, class B =I>
180 : public NoCopyMoveSupport<I,D,B>
181 {
182 public:
183 virtual void
184 copyInto (void*) const override
185 {
186 throw error::Logic{"Copy construction invoked but target allows only move construction"};
187 }
188
189 virtual void
190 moveInto (void* targetStorage) override
191 {
192 D& src = static_cast<D&> (*this);
193 new(targetStorage) D(move(src));
194 }
195
196 // irrelevant for any practical usage, but formally required
197 using NoCopyMoveSupport<I,D,B>::copyInto;
198 using NoCopyMoveSupport<I,D,B>::moveInto;
199 };
200
201
202 template<class I, class D, class B =I>
204 : public MoveSupport<I,D,B>
205 {
206 public:
207 virtual void
208 copyInto (void* targetStorage) const override
209 {
210 D const& src = static_cast<D const&> (*this);
211 new(targetStorage) D(src);
212 }
213
214 using MoveSupport<I,D,B>::copyInto;
215 };
216
217
218 template<class I, class D, class B =I>
220 : public CloneSupport<I,D,B>
221 {
222 public:
223 virtual void
224 copyInto (I& target) const override
225 {
226 D& t = D::downcast(target);
227 D const& s = static_cast<D const&> (*this);
228 t = s;
229 }
230
231 virtual void
232 moveInto (I& target) override
233 {
234 D& t = D::downcast(target);
235 D& s = static_cast<D&> (*this);
236 t = move(s);
237 }
238
239 using CloneSupport<I,D,B>::copyInto;
240 using CloneSupport<I,D,B>::moveInto;
241 }; // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109740
242 // In our case here, calls will always be through VirtualCopySupportInterface
243 // and void* is incompatible with I&, so the warning is irrelevant...
244
245
246
247 namespace { // helpers to select suitable variant of copy support...
248
249 template<class X>
251 : __and_<is_move_constructible<X>
252 ,__not_<is_copy_constructible<X>>
253 ,__not_<is_copy_assignable<X>>
254 >
255 { };
256
257 template<class X>
259 : __and_<is_move_constructible<X>
260 ,is_copy_constructible<X>
261 ,__not_<is_copy_assignable<X>>
262 >
263 { };
264
265 template<class X>
267 : __and_<is_move_constructible<X>
268 ,is_copy_constructible<X>
269 ,is_copy_assignable<X>
270 >
271 { };
272 }
273
274
275
276
280 template<class X, class SEL=void>
282 {
283 template<class I, class D, class B =I>
285 };
286
287 template<class X>
288 struct CopySupport<X, enable_if<supports_only_move<X>> >
289 {
290 template<class I, class D, class B =I>
292 };
293
294 template<class X>
295 struct CopySupport<X, enable_if<supports_cloning<X>> >
296 {
297 template<class I, class D, class B =I>
299 };
300
301 template<class X>
302 struct CopySupport<X, enable_if<supports_copy_and_assignment<X>> >
303 {
304 template<class I, class D, class B =I>
306 };
307
308
309
310
311}} // namespace lib::meta
312#endif /*LIB_META_VIRTUAL_COPY_SUPPORT_H*/
virtual void copyInto(void *targetStorage) const override
virtual void copyInto(I &target) const override
virtual void moveInto(I &target) override
virtual void copyInto(void *) const override
virtual void moveInto(void *targetStorage) override
virtual void copyInto(void *) const override
virtual void moveInto(void *) override
virtual void moveInto(I &) override
virtual void copyInto(I &) const override
virtual void moveInto(IFA &target)=0
virtual void copyInto(void *targetStorage) const =0
virtual void moveInto(void *targetStorage)=0
virtual void copyInto(IFA &target) const =0
Lumiera error handling (C++ interface).
NoCopyMoveSupport< I, D, B > Policy
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Policy to pick a suitable implementation of "virtual copy operations".
Implementation namespace for support and library code.
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207