Boost GIL


variant.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3 
4  Use, modification and distribution are subject to the Boost Software License,
5  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6  http://www.boost.org/LICENSE_1_0.txt).
7 
8  See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 
11 /*************************************************************************************************/
12 
13 #ifndef GIL_DYNAMICIMAGE_VARIANT_HPP
14 #define GIL_DYNAMICIMAGE_VARIANT_HPP
15 
24 
25 #include "../../gil_config.hpp"
26 #include "../../utilities.hpp"
27 #include <cstddef>
28 #include <cassert>
29 #include <algorithm>
30 #include <typeinfo>
31 #include <boost/bind.hpp>
32 #include <boost/utility/enable_if.hpp>
33 #include <boost/mpl/bool.hpp>
34 #include <boost/mpl/transform.hpp>
35 #include <boost/mpl/size.hpp>
36 #include <boost/mpl/sizeof.hpp>
37 #include <boost/mpl/max.hpp>
38 #include <boost/mpl/at.hpp>
39 #include <boost/mpl/fold.hpp>
40 
41 namespace boost { namespace gil {
42 
43 namespace detail {
44  template <typename Types, typename T> struct type_to_index;
45  template <typename Op, typename T> struct reduce;
46  struct destructor_op {
47  typedef void result_type;
48  template <typename T> result_type operator()(const T& t) const { t.~T(); }
49  };
50  template <typename T, typename Bits> void copy_construct_in_place(const T& t, Bits& bits);
51  template <typename Bits> struct copy_construct_in_place_fn;
52  template <typename Types> struct type_to_index_fn;
53 }
88 template <typename Types> // models MPL Random Access Container
89 class variant {
90  // size in bytes of the largest type in Types
91  static const std::size_t MAX_SIZE = mpl::fold<Types, mpl::size_t<0>, mpl::max<mpl::_1, mpl::sizeof_<mpl::_2> > >::type::value;
92  static const std::size_t NUM_TYPES = mpl::size<Types>::value;
93 public:
94  typedef Types types_t;
95 
96  typedef struct { char data[MAX_SIZE]; } base_t; // empty space equal to the size of the largest type in Types
97 
98  // Default constructor - default construct the first type
99  variant() : _index(0) { new(&_bits) typename mpl::at_c<Types,0>::type(); }
100  virtual ~variant() { apply_operation(*this, detail::destructor_op()); }
101 
102  // Throws std::bad_cast if T is not in Types
103  template <typename T> explicit variant(const T& obj){ _index=type_id<T>(); if (_index==NUM_TYPES) throw std::bad_cast(); detail::copy_construct_in_place(obj, _bits); }
104 
105  template <typename Types2> explicit variant(const variant<Types2>& obj) : _index(apply_operation(obj,detail::type_to_index_fn<Types>())) {
106  if (_index==NUM_TYPES) throw std::bad_cast();
107  apply_operation(obj, detail::copy_construct_in_place_fn<base_t>(_bits));
108  }
109 
110  // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
111  template <typename T> explicit variant(T& obj, bool do_swap);
112 
113  template <typename T> variant& operator=(const T& obj) { variant tmp(obj); swap(*this,tmp); return *this; }
114  variant& operator=(const variant& v) { variant tmp(v ); swap(*this,tmp); return *this; }
115 
116  variant(const variant& v) : _index(v._index) { apply_operation(v, detail::copy_construct_in_place_fn<base_t>(_bits)); }
117  template <typename T> void move_in(T& obj) { variant tmp(obj, true); swap(*this,tmp); }
118 
119  template <typename TS> friend bool operator==(const variant<TS>& x, const variant<TS>& y);
120  template <typename TS> friend bool operator!=(const variant<TS>& x, const variant<TS>& y);
121 
122  template <typename T> static bool has_type() { return type_id<T>()!=NUM_TYPES; }
123 
124  template <typename T> const T& _dynamic_cast() const { if (!current_type_is<T>()) throw std::bad_cast(); return *gil_reinterpret_cast_c<const T*>(&_bits); }
125  template <typename T> T& _dynamic_cast() { if (!current_type_is<T>()) throw std::bad_cast(); return *gil_reinterpret_cast < T*>(&_bits); }
126 
127  template <typename T> bool current_type_is() const { return type_id<T>()==_index; }
128 
129  base_t bits() const { return _bits; }
130  std::size_t index() const { return _index; }
131 
132 private:
133  template <typename T> static std::size_t type_id() { return detail::type_to_index<Types,T>::value; }
134 
135  template <typename Cs> friend void swap(variant<Cs>& x, variant<Cs>& y);
136  template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(variant<Types2>& var, UnaryOp op);
137  template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(const variant<Types2>& var, UnaryOp op);
138  template <typename Types1, typename Types2, typename BinaryOp> friend typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op);
139 
140  base_t _bits;
141  std::size_t _index;
142 };
143 
144 namespace detail {
145 
146  template <typename T, typename Bits>
147  void copy_construct_in_place(const T& t, Bits& bits) {
148  T& b=*gil_reinterpret_cast<T*>(&bits);
149  new(&b)T(t); // default-construct
150  }
151 
152  template <typename Bits>
153  struct copy_construct_in_place_fn {
154  typedef void result_type;
155  Bits& _dst;
156  copy_construct_in_place_fn(Bits& dst) : _dst(dst) {}
157 
158  template <typename T> void operator()(const T& src) const { copy_construct_in_place(src,_dst); }
159  };
160 
161  template <typename Bits>
162  struct equal_to_fn {
163  const Bits& _dst;
164  equal_to_fn(const Bits& dst) : _dst(dst) {}
165 
166  typedef bool result_type;
167  template <typename T> result_type operator()(const T& x) const {
168  return x==*gil_reinterpret_cast_c<const T*>(&_dst);
169  }
170  };
171 
172  template <typename Types>
173  struct type_to_index_fn {
174  typedef std::size_t result_type;
175 
176  template <typename T> result_type operator()(const T&) const { return detail::type_to_index<Types,T>::value; }
177  };
178 }
179 
180 // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
181 template <typename Types>
182 template <typename T> variant<Types>::variant(T& obj, bool do_swap) {
183  _index=type_id<T>();
184  if (_index==NUM_TYPES) throw std::bad_cast();
185 
186  if (do_swap) {
187  new(&_bits) T(); // default construct
188  swap(obj, *gil_reinterpret_cast<T*>(&_bits));
189  } else
190  detail::copy_construct_in_place(const_cast<const T&>(obj), _bits);
191 }
192 
193 template <typename Types>
194 void swap(variant<Types>& x, variant<Types>& y) {
195  std::swap(x._bits,y._bits);
196  std::swap(x._index, y._index);
197 }
198 
199 template <typename Types>
200 inline bool operator==(const variant<Types>& x, const variant<Types>& y) {
201  return x._index==y._index && apply_operation(x,detail::equal_to_fn<typename variant<Types>::base_t>(y._bits));
202 }
203 
204 template <typename C>
205 inline bool operator!=(const variant<C>& x, const variant<C>& y) {
206  return !(x==y);
207 }
208 
209 } } // namespace boost::gil
210 
211 #endif
BOOST_FORCEINLINE UnaryOp::result_type apply_operation(variant< Types > &arg, UnaryOp op)
Invokes a generic mutable operation (represented as a unary function object) on a variant...
Definition: apply_operation.hpp:35
Represents a concrete instance of a run-time specified type from a set of typesA concept is typically...
Definition: variant.hpp:89
void swap(const boost::gil::planar_pixel_reference< CR, CS > x, const boost::gil::planar_pixel_reference< CR, CS > y)
swap for planar_pixel_reference
Definition: planar_pixel_reference.hpp:193
Returns the index corresponding to the first occurrance of a given given type in. ...
Definition: utilities.hpp:307