annotate DEPENDENCIES/generic/include/boost/gil/extension/dynamic_image/variant.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 /*
Chris@16 2 Copyright 2005-2007 Adobe Systems Incorporated
Chris@16 3
Chris@16 4 Use, modification and distribution are subject to the Boost Software License,
Chris@16 5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 http://www.boost.org/LICENSE_1_0.txt).
Chris@16 7
Chris@16 8 See http://opensource.adobe.com/gil for most recent version including documentation.
Chris@16 9 */
Chris@16 10
Chris@16 11 /*************************************************************************************************/
Chris@16 12
Chris@16 13 #ifndef GIL_DYNAMICIMAGE_VARIANT_HPP
Chris@16 14 #define GIL_DYNAMICIMAGE_VARIANT_HPP
Chris@16 15
Chris@16 16 ////////////////////////////////////////////////////////////////////////////////////////
Chris@16 17 /// \file
Chris@16 18 /// \brief Support for run-time instantiated types
Chris@16 19 /// \author Lubomir Bourdev and Hailin Jin \n
Chris@16 20 /// Adobe Systems Incorporated
Chris@16 21 /// \date 2005-2007 \n Last updated on September 18, 2007
Chris@16 22 ///
Chris@16 23 ////////////////////////////////////////////////////////////////////////////////////////
Chris@16 24
Chris@16 25 #include "../../gil_config.hpp"
Chris@16 26 #include "../../utilities.hpp"
Chris@16 27 #include <cstddef>
Chris@16 28 #include <cassert>
Chris@16 29 #include <algorithm>
Chris@16 30 #include <typeinfo>
Chris@16 31 #include <boost/bind.hpp>
Chris@16 32
Chris@16 33 #include <boost/mpl/transform.hpp>
Chris@16 34 #include <boost/mpl/size.hpp>
Chris@16 35 #include <boost/mpl/sizeof.hpp>
Chris@16 36 #include <boost/mpl/max.hpp>
Chris@16 37 #include <boost/mpl/at.hpp>
Chris@16 38 #include <boost/mpl/fold.hpp>
Chris@16 39
Chris@16 40 namespace boost { namespace gil {
Chris@16 41
Chris@16 42 namespace detail {
Chris@16 43 template <typename Types, typename T> struct type_to_index;
Chris@16 44 template <typename Op, typename T> struct reduce;
Chris@16 45 struct destructor_op {
Chris@16 46 typedef void result_type;
Chris@16 47 template <typename T> result_type operator()(const T& t) const { t.~T(); }
Chris@16 48 };
Chris@16 49 template <typename T, typename Bits> void copy_construct_in_place(const T& t, Bits& bits);
Chris@16 50 template <typename Bits> struct copy_construct_in_place_fn;
Chris@16 51 }
Chris@16 52 /**
Chris@16 53 \brief Represents a concrete instance of a run-time specified type from a set of types
Chris@16 54 \class variant
Chris@16 55 \ingroup Variant
Chris@16 56
Chris@16 57 A concept is typically modeled by a collection of different types. They may be instantiations
Chris@16 58 of a templated type with different template parameters or even completely unrelated types.
Chris@16 59
Chris@16 60 We call the type with which the concept is instantiated in a given place in the code "the concrete type".
Chris@16 61 The concrete type must be chosen at compile time, which sometimes is a severe limitation.
Chris@16 62 Consider, for example, having an image concept modeled by an image class templated over the color space.
Chris@16 63 It would be difficult to write a function that reads an image from file preserving its native color space, since the
Chris@16 64 type of the return value is only available at run time. It would be difficult to store images of different color
Chris@16 65 spaces in the same container or apply operations on them uniformly.
Chris@16 66
Chris@16 67 The variant class addresses this deficiency. It allows for run-time instantiation of a class from a given set of allowed classes
Chris@16 68 specified at compile time. For example, the set of allowed classes may include 8-bit and 16-bit RGB and CMYK images. Such a variant
Chris@16 69 can be constructed with rgb8_image_t and then assigned a cmyk16_image_t.
Chris@16 70
Chris@16 71 The variant has a templated constructor, which allows us to construct it with any concrete type instantiation. It can also perform a generic
Chris@16 72 operation on the concrete type via a call to apply_operation. The operation must be provided as a function object whose application
Chris@16 73 operator has a single parameter which can be instantiated with any of the allowed types of the variant.
Chris@16 74
Chris@16 75 variant breaks down the instantiated type into a non-templated underlying base type and a unique instantiation
Chris@16 76 type identifier. In the most common implementation the concrete instantiation in stored 'in-place' - in 'bits_t'.
Chris@16 77 bits_t contains sufficient space to fit the largest of the instantiated objects.
Chris@16 78
Chris@16 79 GIL's variant is similar to boost::variant in spirit (hence we borrow the name from there) but it differs in several ways from the current boost
Chris@16 80 implementation. Most notably, it does not take a variable number of template parameters but a single parameter defining the type enumeration. As
Chris@16 81 such it can be used more effectively in generic code.
Chris@16 82
Chris@16 83 The Types parameter specifies the set of allowable types. It models MPL Random Access Container
Chris@16 84 */
Chris@16 85
Chris@16 86 template <typename Types> // models MPL Random Access Container
Chris@16 87 class variant {
Chris@16 88 // size in bytes of the largest type in Types
Chris@16 89 static const std::size_t MAX_SIZE = mpl::fold<Types, mpl::size_t<0>, mpl::max<mpl::_1, mpl::sizeof_<mpl::_2> > >::type::value;
Chris@16 90 static const std::size_t NUM_TYPES = mpl::size<Types>::value;
Chris@16 91 public:
Chris@16 92 typedef Types types_t;
Chris@16 93
Chris@16 94 typedef struct { char data[MAX_SIZE]; } base_t; // empty space equal to the size of the largest type in Types
Chris@16 95
Chris@16 96 // Default constructor - default construct the first type
Chris@16 97 variant() : _index(0) { new(&_bits) typename mpl::at_c<Types,0>::type(); }
Chris@16 98 virtual ~variant() { apply_operation(*this, detail::destructor_op()); }
Chris@16 99
Chris@16 100 // Throws std::bad_cast if T is not in Types
Chris@16 101 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); }
Chris@16 102
Chris@16 103 // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
Chris@16 104 template <typename T> explicit variant(T& obj, bool do_swap);
Chris@16 105
Chris@16 106 template <typename T> variant& operator=(const T& obj) { variant tmp(obj); swap(*this,tmp); return *this; }
Chris@16 107 variant& operator=(const variant& v) { variant tmp(v ); swap(*this,tmp); return *this; }
Chris@16 108
Chris@16 109 variant(const variant& v) : _index(v._index) { apply_operation(v, detail::copy_construct_in_place_fn<base_t>(_bits)); }
Chris@16 110 template <typename T> void move_in(T& obj) { variant tmp(obj, true); swap(*this,tmp); }
Chris@16 111
Chris@16 112 template <typename TS> friend bool operator==(const variant<TS>& x, const variant<TS>& y);
Chris@16 113 template <typename TS> friend bool operator!=(const variant<TS>& x, const variant<TS>& y);
Chris@16 114
Chris@16 115 template <typename T> static bool has_type() { return type_id<T>()!=NUM_TYPES; }
Chris@16 116
Chris@16 117 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); }
Chris@16 118 template <typename T> T& _dynamic_cast() { if (!current_type_is<T>()) throw std::bad_cast(); return *gil_reinterpret_cast < T*>(&_bits); }
Chris@16 119
Chris@16 120 template <typename T> bool current_type_is() const { return type_id<T>()==_index; }
Chris@16 121
Chris@16 122 base_t bits() const { return _bits; }
Chris@16 123 std::size_t index() const { return _index; }
Chris@16 124
Chris@16 125 private:
Chris@16 126 template <typename T> static std::size_t type_id() { return detail::type_to_index<Types,T>::value; }
Chris@16 127
Chris@16 128 template <typename Cs> friend void swap(variant<Cs>& x, variant<Cs>& y);
Chris@16 129 template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(variant<Types2>& var, UnaryOp op);
Chris@16 130 template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(const variant<Types2>& var, UnaryOp op);
Chris@16 131 template <typename Types1, typename Types2, typename BinaryOp> friend typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op);
Chris@16 132
Chris@16 133 base_t _bits;
Chris@16 134 std::size_t _index;
Chris@16 135 };
Chris@16 136
Chris@16 137 namespace detail {
Chris@16 138
Chris@16 139 template <typename T, typename Bits>
Chris@16 140 void copy_construct_in_place(const T& t, Bits& bits) {
Chris@16 141 T& b=*gil_reinterpret_cast<T*>(&bits);
Chris@16 142 new(&b)T(t); // default-construct
Chris@16 143 }
Chris@16 144
Chris@16 145 template <typename Bits>
Chris@16 146 struct copy_construct_in_place_fn {
Chris@16 147 typedef void result_type;
Chris@16 148 Bits& _dst;
Chris@16 149 copy_construct_in_place_fn(Bits& dst) : _dst(dst) {}
Chris@16 150
Chris@16 151 template <typename T> void operator()(const T& src) const { copy_construct_in_place(src,_dst); }
Chris@16 152 };
Chris@16 153
Chris@16 154 template <typename Bits>
Chris@16 155 struct equal_to_fn {
Chris@16 156 const Bits& _dst;
Chris@16 157 equal_to_fn(const Bits& dst) : _dst(dst) {}
Chris@16 158
Chris@16 159 typedef bool result_type;
Chris@16 160 template <typename T> result_type operator()(const T& x) const {
Chris@16 161 return x==*gil_reinterpret_cast_c<const T*>(&_dst);
Chris@16 162 }
Chris@16 163 };
Chris@16 164 }
Chris@16 165
Chris@16 166 // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
Chris@16 167 template <typename Types>
Chris@16 168 template <typename T> variant<Types>::variant(T& obj, bool do_swap) {
Chris@16 169 _index=type_id<T>();
Chris@16 170 if (_index==NUM_TYPES) throw std::bad_cast();
Chris@16 171
Chris@16 172 if (do_swap) {
Chris@16 173 new(&_bits) T(); // default construct
Chris@16 174 swap(obj, *gil_reinterpret_cast<T*>(&_bits));
Chris@16 175 } else
Chris@16 176 detail::copy_construct_in_place(const_cast<const T&>(obj), _bits);
Chris@16 177 }
Chris@16 178
Chris@16 179 template <typename Types>
Chris@16 180 void swap(variant<Types>& x, variant<Types>& y) {
Chris@16 181 std::swap(x._bits,y._bits);
Chris@16 182 std::swap(x._index, y._index);
Chris@16 183 }
Chris@16 184
Chris@16 185 template <typename Types>
Chris@16 186 inline bool operator==(const variant<Types>& x, const variant<Types>& y) {
Chris@16 187 return x._index==y._index && apply_operation(x,detail::equal_to_fn<typename variant<Types>::base_t>(y._bits));
Chris@16 188 }
Chris@16 189
Chris@16 190 template <typename C>
Chris@16 191 inline bool operator!=(const variant<C>& x, const variant<C>& y) {
Chris@16 192 return !(x==y);
Chris@16 193 }
Chris@16 194
Chris@16 195 } } // namespace boost::gil
Chris@16 196
Chris@16 197 #endif