variant.hppGo to the documentation of this file.00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 00004 Use, modification and distribution are subject to the Boost Software License, 00005 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 00006 http://www.boost.org/LICENSE_1_0.txt). 00007 00008 See http://opensource.adobe.com/gil for most recent version including documentation. 00009 */ 00010 00011 /*************************************************************************************************/ 00012 00013 #ifndef GIL_DYNAMICIMAGE_VARIANT_HPP 00014 #define GIL_DYNAMICIMAGE_VARIANT_HPP 00015 00024 00025 #include "../../gil_config.hpp" 00026 #include "../../utilities.hpp" 00027 #include <cstddef> 00028 #include <cassert> 00029 #include <algorithm> 00030 #include <typeinfo> 00031 #include <boost/bind.hpp> 00032 00033 #include <boost/mpl/transform.hpp> 00034 #include <boost/mpl/size.hpp> 00035 #include <boost/mpl/sizeof.hpp> 00036 #include <boost/mpl/max.hpp> 00037 #include <boost/mpl/at.hpp> 00038 #include <boost/mpl/fold.hpp> 00039 00040 namespace boost { namespace gil { 00041 00042 namespace detail { 00043 template <typename Types, typename T> struct type_to_index; 00044 template <typename Op, typename T> struct reduce; 00045 struct destructor_op { 00046 typedef void result_type; 00047 template <typename T> result_type operator()(const T& t) const { t.~T(); } 00048 }; 00049 template <typename T, typename Bits> void copy_construct_in_place(const T& t, Bits& bits); 00050 template <typename Bits> struct copy_construct_in_place_fn; 00051 } 00086 template <typename Types> // models MPL Random Access Container 00087 class variant { 00088 // size in bytes of the largest type in Types 00089 static const std::size_t MAX_SIZE = mpl::fold<Types, mpl::size_t<0>, mpl::max<mpl::_1, mpl::sizeof_<mpl::_2> > >::type::value; 00090 static const std::size_t NUM_TYPES = mpl::size<Types>::value; 00091 public: 00092 typedef Types types_t; 00093 00094 typedef struct { char data[MAX_SIZE]; } base_t; // empty space equal to the size of the largest type in Types 00095 00096 // Default constructor - default construct the first type 00097 variant() : _index(0) { new(&_bits) typename mpl::at_c<Types,0>::type(); } 00098 virtual ~variant() { apply_operation(*this, detail::destructor_op()); } 00099 00100 // Throws std::bad_cast if T is not in Types 00101 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); } 00102 00103 // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call 00104 template <typename T> explicit variant(T& obj, bool do_swap); 00105 00106 template <typename T> variant& operator=(const T& obj) { variant tmp(obj); swap(*this,tmp); return *this; } 00107 variant& operator=(const variant& v) { variant tmp(v ); swap(*this,tmp); return *this; } 00108 00109 variant(const variant& v) : _index(v._index) { apply_operation(v, detail::copy_construct_in_place_fn<base_t>(_bits)); } 00110 template <typename T> void move_in(T& obj) { variant tmp(obj, true); swap(*this,tmp); } 00111 00112 template <typename TS> friend bool operator==(const variant<TS>& x, const variant<TS>& y); 00113 template <typename TS> friend bool operator!=(const variant<TS>& x, const variant<TS>& y); 00114 00115 template <typename T> static bool has_type() { return type_id<T>()!=NUM_TYPES; } 00116 00117 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); } 00118 template <typename T> T& _dynamic_cast() { if (!current_type_is<T>()) throw std::bad_cast(); return *gil_reinterpret_cast < T*>(&_bits); } 00119 00120 template <typename T> bool current_type_is() const { return type_id<T>()==_index; } 00121 00122 private: 00123 template <typename T> static std::size_t type_id() { return detail::type_to_index<Types,T>::value; } 00124 00125 template <typename Cs> friend void swap(variant<Cs>& x, variant<Cs>& y); 00126 template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(variant<Types2>& var, UnaryOp op); 00127 template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(const variant<Types2>& var, UnaryOp op); 00128 template <typename Types1, typename Types2, typename BinaryOp> friend typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op); 00129 00130 base_t _bits; 00131 std::size_t _index; 00132 }; 00133 00134 namespace detail { 00135 00136 template <typename T, typename Bits> 00137 void copy_construct_in_place(const T& t, Bits& bits) { 00138 T& b=*gil_reinterpret_cast<T*>(&bits); 00139 new(&b)T(t); // default-construct 00140 } 00141 00142 template <typename Bits> 00143 struct copy_construct_in_place_fn { 00144 typedef void result_type; 00145 Bits& _dst; 00146 copy_construct_in_place_fn(Bits& dst) : _dst(dst) {} 00147 00148 template <typename T> void operator()(const T& src) const { copy_construct_in_place(src,_dst); } 00149 }; 00150 00151 template <typename Bits> 00152 struct equal_to_fn { 00153 const Bits& _dst; 00154 equal_to_fn(const Bits& dst) : _dst(dst) {} 00155 00156 typedef bool result_type; 00157 template <typename T> result_type operator()(const T& x) const { 00158 return x==*gil_reinterpret_cast_c<const T*>(&_dst); 00159 } 00160 }; 00161 } 00162 00163 // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call 00164 template <typename Types> 00165 template <typename T> variant<Types>::variant(T& obj, bool do_swap) { 00166 _index=type_id<T>(); 00167 if (_index==NUM_TYPES) throw std::bad_cast(); 00168 00169 if (do_swap) { 00170 new(&_bits) T(); // default construct 00171 swap(obj, *gil_reinterpret_cast<T*>(&_bits)); 00172 } else 00173 detail::copy_construct_in_place(const_cast<const T&>(obj), _bits); 00174 } 00175 00176 template <typename Types> 00177 void swap(variant<Types>& x, variant<Types>& y) { 00178 std::swap(x._bits,y._bits); 00179 std::swap(x._index, y._index); 00180 } 00181 00182 template <typename Types> 00183 inline bool operator==(const variant<Types>& x, const variant<Types>& y) { 00184 return x._index==y._index && apply_operation(x,detail::equal_to_fn<typename variant<Types>::base_t>(y._bits)); 00185 } 00186 00187 template <typename C> 00188 inline bool operator!=(const variant<C>& x, const variant<C>& y) { 00189 return !(x==y); 00190 } 00191 00192 } } // namespace boost::gil 00193 00194 #endif Generated on Sat May 2 13:50:15 2009 for Generic Image Library by 1.5.6 |