TPIE

11a2c2d
container.h
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2015, The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 
20 #ifndef __TPIE_PIPELINING_PIPE_CONTAINER_H__
21 #define __TPIE_PIPELINING_PIPE_CONTAINER_H__
22 
23 #include <type_traits>
24 #include <memory>
25 #include <typeinfo>
26 
27 namespace tpie::pipelining {
28 
29 template <typename T>
30 T & move_if_movable(typename std::remove_reference<T>::type & t,
31  typename std::enable_if<!std::is_move_constructible<T>::value>::type* = 0) {
32  return t;
33 }
34 
35 template <typename T>
36 T && move_if_movable(typename std::remove_reference<T>::type & t,
37  typename std::enable_if<std::is_move_constructible<T>::value>::type* = 0) {
38  return static_cast<T&&>(t);
39 }
40 
41 template <typename T>
42 T & move_if_movable_rvalue(typename std::remove_reference<T>::type & t,
43  typename std::enable_if<
44  !std::is_move_constructible<T>::value ||
45  !std::is_rvalue_reference<T>::value
46  >::type* = 0) {
47  return t;
48 }
49 
50 template <typename T>
51 T && move_if_movable_rvalue(typename std::remove_reference<T>::type & t,
52  typename std::enable_if<
53  std::is_move_constructible<T>::value &&
54  std::is_rvalue_reference<T>::value
55  >::type* = 0) {
56  return static_cast<T&&>(t);
57 }
58 
59 
60 template <typename ... TT>
61 class container {};
62 
63 template <typename T, typename ... TT>
64 struct container<T, TT...> : public container<TT...> {
65  container(const container &) = delete;
66  container() = delete;
67 
68  template <typename T2, typename ... TT2>
69  container(T2 && t, TT2 && ... tt)
70  : container<TT...>(std::forward<TT2>(tt)...)
71  , v(move_if_movable_rvalue<T2&&>(t)) {}
72 
73  container(container && o)
74  : container<TT...>(std::forward<container<TT...> >(o))
75  , v(move_if_movable<T>(o.v)) {}
76 
77  T v;
78 };
79 
80 namespace bits {
81 template <int i, typename T, typename ...TT>
82 struct get_impl {
83  typedef typename get_impl<i-1, TT...>::type type;
84  static type & get(container<T, TT...> & cc) {return get_impl<i-1, TT...>::get(cc);}
85  static const type & get(const container<T, TT...> & cc) {return get_impl<i-1, TT...>::get(cc);}
86 };
87 
88 template <typename T, typename ...TT>
89 struct get_impl<0, T, TT...> {
90  typedef T type;
91  static type & get(container<T, TT...> & cc) {return cc.v;}
92  static const type & get(const container<T, TT...> & cc) {return cc.v;}
93 };
94 } //namespace bits
95 
96 
97 template <int i, typename ...T>
98 typename bits::get_impl<i, T...>::type & get(container<T...> & c) {
100 }
101 
102 template <int i, typename ...T>
103 const typename bits::get_impl<i, T...>::type & get(const container<T...> & c) {
104  return bits::get_impl<i, T...>::get(c);
105 }
106 
107 namespace bits {
108 template<int ... S>
109 struct dispatch {
110  template <typename F, typename ... T1, typename ... T2>
111  static F run_move(container<T1...> & t, T2 &&... o) {
112  return F(std::move(o)..., move_if_movable<T1>(get<S>(t))...);
113  }
114 
115  template <typename F, typename ... T1, typename ... T2>
116  static F run_copy(container<T1...> & t, T2 &&... o) {
117  return F(std::move(o)..., get<S>(t)...);
118  }
119 };
120 
121 template<int N, int ...S>
122 struct dispatch_gen : dispatch_gen<N-1, N-1, S...> { };
123 
124 template<int ...S>
125 struct dispatch_gen<0, S...> {
126  typedef dispatch<S...> type;
127 };
128 
129 } //namespace bits
130 
131 
132 template <typename F, typename ... T1, typename ... T2>
133 F container_construct(container<T1...> & cont, T2 && ... a) {
134  return bits::dispatch_gen<sizeof...(T1)>::type::template run_move<F>(cont, std::move(a)...);
135 }
136 
137 template <typename F, typename ... T1, typename ... T2>
138 F container_construct_copy(container<T1...> & cont, T2 && ... a) {
139  return bits::dispatch_gen<sizeof...(T1)>::type::template run_copy<F>(cont, std::move(a)...);
140 }
141 
142 class bad_any_noncopyable_copy: public std::exception {
143 public:
144  const char * what() const noexcept override {return "bad any_noncopyable copy";}
145 };
146 
147 
148 namespace bits {
149 
151 public:
152  virtual ~any_noncopyable_cont_base() {};
153  virtual const std::type_info & type() const {
154  return typeid(void);
155  }
156  virtual any_noncopyable_cont_base * copy() const = 0;
157 };
158 
159 template <typename T, bool can_copy = std::is_copy_constructible<T>::value>
161 public:
162  any_noncopyable_cont(T value): value(move_if_movable<T>(value)) {}
163  T value;
164  const std::type_info & type() const override {
165  return typeid(value);
166  }
167 
168  any_noncopyable_cont_base * copy() const override {
169  throw bad_any_noncopyable_copy();
170  }
171 };
172 
173 template <typename T>
175 public:
176  any_noncopyable_cont(T value): value(move_if_movable<T>(value)) {}
177  T value;
178  const std::type_info & type() const override {
179  return typeid(value);
180  }
181 
182  any_noncopyable_cont_base * copy() const override {
183  return new any_noncopyable_cont<T, true>(value);
184  }
185 };
186 
187 
188 } //namespace bits
189 
190 class bad_any_noncopyable_cast: public std::bad_cast {
191 public:
192  const char * what() const noexcept override {return "bad any_noncopyable cast";}
193 };
194 
196 public:
197  template <typename T>
198  explicit any_noncopyable(T t) {
199  cont = std::unique_ptr<bits::any_noncopyable_cont_base>(
200  new bits::any_noncopyable_cont<T>(move_if_movable<T>(t)));
201  }
202 
203  any_noncopyable() = default;
204  any_noncopyable(const any_noncopyable &) = delete;
205  any_noncopyable(any_noncopyable &&) = default;
206  any_noncopyable & operator=(const any_noncopyable & o) = delete;
207  any_noncopyable & operator=(any_noncopyable && o) = default;
208 
209  template <typename T>
210  any_noncopyable & operator=(T t) {
211  cont = std::unique_ptr<bits::any_noncopyable_cont_base>(
212  new bits::any_noncopyable_cont<T>(move_if_movable<T>(t)));
213  return *this;
214  }
215 
216  explicit operator bool() {return (bool)cont;}
217 
218  void reset() {cont.reset();}
219 
220  any_noncopyable copy() const {
221  return any_noncopyable(cont->copy());
222  }
223 
224  template <typename T>
225  friend const T & any_cast(const any_noncopyable & a);
226 
227  template <typename T>
228  friend T & any_cast(any_noncopyable & a);
229 
230  friend void swap(any_noncopyable & l, any_noncopyable & r);
231 
232  const std::type_info & type() const {
233  if (!cont) return typeid(void);
234  auto val = cont.get();
235  return val->type();
236  }
237 private:
239  : cont(elm) {}
240 
241  std::unique_ptr<bits::any_noncopyable_cont_base> cont;
242 };
243 
244 template <typename T>
245 const T & any_cast(const any_noncopyable & a) {
246  if (!a.cont) throw bad_any_noncopyable_cast();
247  auto val = a.cont.get();
248  if (typeid(*val) != typeid(bits::any_noncopyable_cont<T>)) throw bad_any_noncopyable_cast();
249  return static_cast<const bits::any_noncopyable_cont<T>*>(val)->value;
250 }
251 
252 template <typename T>
253 T & any_cast(any_noncopyable & a) {
254  if (!a.cont) throw bad_any_noncopyable_cast();
255  auto val = a.cont.get();
256  if (typeid(*val) != typeid(bits::any_noncopyable_cont<T>)) throw bad_any_noncopyable_cast();
257  return static_cast<bits::any_noncopyable_cont<T>*>(val)->value;
258 }
259 
260 inline void swap(any_noncopyable & l, any_noncopyable & r) {std::swap(l.cont, r.cont);}
261 
262 } //namespace tpie::pipelining
263 #endif //__TPIE_PIPELINING_PIPE_CONTAINER_H__
tpie::pipelining
pipelining/factory_base.h Base class of pipelining factories
Definition: ami_glue.h:23
tpie::pipelining::bits::get_impl
Definition: container.h:82
tpie::pipelining::container< T, TT... >
Definition: container.h:64
tpie::pipelining::bits::any_noncopyable_cont< T, true >
Definition: container.h:174
tpie::pipelining::bad_any_noncopyable_copy
Definition: container.h:142
tpie::pipelining::bits::dispatch_gen
Definition: container.h:122
tpie::pipelining::container
Definition: container.h:61
tpie::pipelining::bad_any_noncopyable_cast
Definition: container.h:190
tpie::pipelining::bits::any_noncopyable_cont_base
Definition: container.h:150
tpie::pipelining::bits::any_noncopyable_cont
Definition: container.h:160
tpie::pipelining::bits::dispatch
Definition: container.h:109
tpie::pipelining::any_noncopyable
Definition: container.h:195