diff --git a/.appveyor.yml b/.appveyor.yml index 199a093678..358db92a29 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -94,6 +94,7 @@ before_build: - git submodule --quiet update --init libs/preprocessor - git submodule --quiet update --init libs/test - git submodule --quiet update --init libs/type_traits + - git submodule --quiet update --init libs/variant ## Transitive (of GIL tests too) - git submodule --quiet update --init libs/atomic - git submodule --quiet update --init libs/bind diff --git a/.travis.yml b/.travis.yml index 1f492c730c..4791b317c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -213,6 +213,7 @@ install: - git submodule --quiet update --init libs/preprocessor - git submodule --quiet update --init libs/test - git submodule --quiet update --init libs/type_traits + - git submodule --quiet update --init libs/variant ## Transitive (of GIL tests too) - git submodule --quiet update --init libs/atomic - git submodule --quiet update --init libs/bind diff --git a/include/boost/gil/extension/dynamic_image/any_image.hpp b/include/boost/gil/extension/dynamic_image/any_image.hpp index 96b2a259b8..40b9e361b8 100644 --- a/include/boost/gil/extension/dynamic_image/any_image.hpp +++ b/include/boost/gil/extension/dynamic_image/any_image.hpp @@ -9,6 +9,7 @@ #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_HPP #include +#include #include @@ -63,8 +64,8 @@ namespace detail { /// In particular, its \p view and \p const_view methods return \p any_image_view, which does not fully model ImageViewConcept. See \p any_image_view for more. //////////////////////////////////////////////////////////////////////////////////////// template -class any_image : public variant { - using parent_t = variant; +class any_image : public make_variant_over::type { + using parent_t = typename make_variant_over::type; public: using const_view_t = any_image_view::type>; using view_t = any_image_view::type>; @@ -76,11 +77,11 @@ class any_image : public variant { template explicit any_image(const T& obj) : parent_t(obj) {} template explicit any_image(T& obj, bool do_swap) : parent_t(obj,do_swap) {} any_image(const any_image& v) : parent_t((const parent_t&)v) {} - template any_image(const any_image& v) : parent_t((const variant&)v) {} + template any_image(const any_image& v) : parent_t((const typename make_variant_over::type&)v) {} template any_image& operator=(const T& obj) { parent_t::operator=(obj); return *this; } any_image& operator=(const any_image& v) { parent_t::operator=((const parent_t&)v); return *this;} - template any_image& operator=(const any_image& v) { parent_t::operator=((const variant&)v); return *this;} + template any_image& operator=(const any_image& v) { parent_t::operator=((const typename make_variant_over::type&)v); return *this;} void recreate(const point_t& dims, unsigned alignment=1) { diff --git a/include/boost/gil/extension/dynamic_image/any_image_view.hpp b/include/boost/gil/extension/dynamic_image/any_image_view.hpp index 4c68ba7e36..84760e1c34 100644 --- a/include/boost/gil/extension/dynamic_image/any_image_view.hpp +++ b/include/boost/gil/extension/dynamic_image/any_image_view.hpp @@ -8,7 +8,7 @@ #ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_VIEW_HPP #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_VIEW_HPP -#include +#include #include #include @@ -57,8 +57,8 @@ namespace detail { /// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p apply_operation(runtime_view, algorithm_fn); //////////////////////////////////////////////////////////////////////////////////////// template -class any_image_view : public variant { - using parent_t = variant; +class any_image_view : public make_variant_over::type { + using parent_t = typename make_variant_over::type; public: using const_t = any_image_view::type>; using x_coord_t = std::ptrdiff_t; @@ -68,11 +68,11 @@ class any_image_view : public variant { any_image_view() : parent_t() {} template explicit any_image_view(const T& obj) : parent_t(obj) {} any_image_view(const any_image_view& v) : parent_t((const parent_t&)v) {} - template any_image_view(const any_image_view& v) : parent_t((const variant&)v) {} + template any_image_view(const any_image_view& v) : parent_t((const typename make_variant_over::type&)v) {} template any_image_view& operator=(const T& obj) { parent_t::operator=(obj); return *this; } any_image_view& operator=(const any_image_view& v) { parent_t::operator=((const parent_t&)v); return *this;} - template any_image_view& operator=(const any_image_view& v) { parent_t::operator=((const variant&)v); return *this;} + template any_image_view& operator=(const any_image_view& v) { parent_t::operator=((const typename make_variant_over::type&)v); return *this;} std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); } point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); } diff --git a/include/boost/gil/extension/dynamic_image/apply_operation.hpp b/include/boost/gil/extension/dynamic_image/apply_operation.hpp index 963ae034fa..528bb7f062 100644 --- a/include/boost/gil/extension/dynamic_image/apply_operation.hpp +++ b/include/boost/gil/extension/dynamic_image/apply_operation.hpp @@ -8,8 +8,7 @@ #ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_HPP #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_HPP -#include -#include +#include #ifdef BOOST_GIL_DOXYGEN_ONLY #undef BOOST_GIL_REDUCE_CODE_BLOAT @@ -30,9 +29,11 @@ namespace boost { namespace gil { template BOOST_FORCEINLINE auto apply_operation(variant& arg, UnaryOp op) +#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) -> typename UnaryOp::result_type +#endif { - return apply_operation_base(arg._bits, arg._index ,op); + return apply_visitor(op, arg); } /// \ingroup Variant @@ -40,9 +41,11 @@ auto apply_operation(variant& arg, UnaryOp op) template BOOST_FORCEINLINE auto apply_operation(variant const& arg, UnaryOp op) +#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) -> typename UnaryOp::result_type +#endif { - return apply_operation_basec(arg._bits, arg._index ,op); + return apply_visitor(op, arg); } /// \ingroup Variant @@ -53,10 +56,12 @@ auto apply_operation( variant const& arg1, variant const& arg2, BinaryOp op) +#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) -> typename BinaryOp::result_type +#endif { - return apply_operation_base( - arg1._bits, arg1._index, arg2._bits, arg2._index, op); + return apply_visitor( + op, arg1, arg2); } }} // namespace boost::gil diff --git a/include/boost/gil/extension/dynamic_image/apply_operation_base.hpp b/include/boost/gil/extension/dynamic_image/apply_operation_base.hpp deleted file mode 100644 index 82d58b1f1f..0000000000 --- a/include/boost/gil/extension/dynamic_image/apply_operation_base.hpp +++ /dev/null @@ -1,175 +0,0 @@ -// -// Copyright 2005-2007 Adobe Systems Incorporated -// -// Distributed under the Boost Software License, Version 1.0 -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_BASE_HPP -#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_BASE_HPP - -#include - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace gil { - -/// Given an object with run-time specified type (denoted as an array of Bits, -/// dynamic index, and a static set of Types) and a generic operation, -/// casts the object to its appropriate type and applies the operation - -/* -GENERATE_APPLY_FWD_OPS generates for every N functions that look like this (for N==2): - - template <> struct apply_operation_fwd_fn<3> { - template - typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const { - using T0 = typename mpl::begin::type; - using T1 = typename mpl::next::type; - using T2 = typename mpl::next::type; - switch (index) { - case 0: return op(reinterpret_cast::type&>(bits)); - case 1: return op(reinterpret_cast::type&>(bits)); - case 2: return op(reinterpret_cast::type&>(bits)); - } - throw; - } - - template - typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { - using T0 = typename mpl::begin::type; - using T1 = typename mpl::next::type; - using T2 = typename mpl::next::type; - switch (index) { - case 0: return op(reinterpret_cast::type&>(bits)); - case 1: return op(reinterpret_cast::type&>(bits)); - case 2: return op(reinterpret_cast::type&>(bits)); - } - throw; - } - }; -*/ - -// TODO: Review, simplify, refactor, modernize (e.g. typedef to using) --mloskot -#define GIL_FWD_TYPEDEFS(z, N, text) T##N; typedef typename mpl::next::type -#define GIL_FWD_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast::type*>(&bits)); -#define GIL_FWD_CONST_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast_c::type*>(&bits)); - -#define GIL_FWD_CASE_WITH_INFO(z, N, SUM) case N: return op(*gil_reinterpret_cast::type*>(&bits), info); -#define GIL_FWD_CONST_CASE_WITH_INFO(z, N, SUM) case N: return op(*gil_reinterpret_cast_c::type*>(&bits), info); - -#define GIL_APPLY_FWD_OP(z, N, text) \ - template <> struct apply_operation_fwd_fn { \ - template \ - typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const { \ - typedef typename mpl::begin::type \ - BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ - T##N; \ - switch (index) { \ - BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE, BOOST_PP_EMPTY) \ - } \ - throw; \ - } \ - template \ - typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { \ - typedef typename mpl::begin::type \ - BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ - T##N; \ - switch (index) { \ - BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE,BOOST_PP_EMPTY) \ - } \ - throw; \ - } \ - template \ - typename UnaryOp::result_type apply(Bits& bits, std::size_t index, const Info& info, UnaryOp op) const { \ - typedef typename mpl::begin::type \ - BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ - T##N; \ - switch (index) { \ - BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE_WITH_INFO, BOOST_PP_EMPTY) \ - } \ - throw; \ - } \ - template \ - typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, const Info& info, UnaryOp op) const { \ - typedef typename mpl::begin::type \ - BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ - T##N; \ - switch (index) { \ - BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE_WITH_INFO,BOOST_PP_EMPTY) \ - } \ - throw; \ - } \ - }; - -#define GIL_GENERATE_APPLY_FWD_OPS(N) BOOST_PP_REPEAT(N, GIL_APPLY_FWD_OP, BOOST_PP_EMPTY) - -namespace detail { -template struct apply_operation_fwd_fn {}; - -// Create specializations of apply_operation_fn for each N 0..100 -GIL_GENERATE_APPLY_FWD_OPS(99) -} // namespace detail - -// unary application -template -typename Op::result_type BOOST_FORCEINLINE apply_operation_basec(const Bits& bits, std::size_t index, Op op) { - return detail::apply_operation_fwd_fn::value>().template applyc(bits,index,op); -} - -// unary application -template -typename Op::result_type BOOST_FORCEINLINE apply_operation_base( Bits& bits, std::size_t index, Op op) { - return detail::apply_operation_fwd_fn::value>().template apply(bits,index,op); -} - -namespace detail { - template - struct reduce_bind1 { - const T2& _t2; - Op& _op; - - using result_type = typename Op::result_type; - - reduce_bind1(const T2& t2, Op& op) : _t2(t2), _op(op) {} - - template BOOST_FORCEINLINE result_type operator()(const T1& t1) { return _op(t1, _t2); } - }; - - template - struct reduce_bind2 { - const Bits1& _bits1; - std::size_t _index1; - Op& _op; - - using result_type = typename Op::result_type; - - reduce_bind2(const Bits1& bits1, std::size_t index1, Op& op) : _bits1(bits1), _index1(index1), _op(op) {} - - template BOOST_FORCEINLINE result_type operator()(const T2& t2) { - return apply_operation_basec(_bits1, _index1, reduce_bind1(t2, _op)); - } - }; -} // namespace detail - -// Binary application by applying on each dimension separately -template -static typename Op::result_type BOOST_FORCEINLINE apply_operation_base(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) { - return apply_operation_basec(bits2,index2,detail::reduce_bind2(bits1,index1,op)); -} - -#undef GIL_FWD_TYPEDEFS -#undef GIL_FWD_CASE -#undef GIL_FWD_CONST_CASE -#undef GIL_APPLY_FWD_OP -#undef GIL_GENERATE_APPLY_FWD_OPS -#undef BHS - -}} // namespace boost::gil - -#endif diff --git a/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp b/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp index 0fa2d39012..f87894459b 100644 --- a/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp +++ b/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include // FIXME: Include what you use! diff --git a/include/boost/gil/extension/dynamic_image/variant.hpp b/include/boost/gil/extension/dynamic_image/variant.hpp deleted file mode 100644 index 6561726d07..0000000000 --- a/include/boost/gil/extension/dynamic_image/variant.hpp +++ /dev/null @@ -1,199 +0,0 @@ -// -// Copyright 2005-2007 Adobe Systems Incorporated -// -// Distributed under the Boost Software License, Version 1.0 -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_VARIANT_HPP -#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_VARIANT_HPP - -// TODO: Replace with C++17 std::variant? - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace boost { namespace gil { - -// Support for run-time instantiated types - -namespace detail { - template struct type_to_index; - template struct reduce; - struct destructor_op { - using result_type = void; - template result_type operator()(const T& t) const { t.~T(); } - }; - template void copy_construct_in_place(const T& t, Bits& bits); - template struct copy_construct_in_place_fn; - template struct type_to_index_fn; -} -/** -\brief Represents a concrete instance of a run-time specified type from a set of types -\class variant -\ingroup Variant - -A concept is typically modeled by a collection of different types. They may be instantiations -of a templated type with different template parameters or even completely unrelated types. - -We call the type with which the concept is instantiated in a given place in the code "the concrete type". -The concrete type must be chosen at compile time, which sometimes is a severe limitation. -Consider, for example, having an image concept modeled by an image class templated over the color space. -It would be difficult to write a function that reads an image from file preserving its native color space, since the -type of the return value is only available at run time. It would be difficult to store images of different color -spaces in the same container or apply operations on them uniformly. - -The variant class addresses this deficiency. It allows for run-time instantiation of a class from a given set of allowed classes -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 -can be constructed with rgb8_image_t and then assigned a cmyk16_image_t. - -The variant has a templated constructor, which allows us to construct it with any concrete type instantiation. It can also perform a generic -operation on the concrete type via a call to apply_operation. The operation must be provided as a function object whose application -operator has a single parameter which can be instantiated with any of the allowed types of the variant. - -variant breaks down the instantiated type into a non-templated underlying base type and a unique instantiation -type identifier. In the most common implementation the concrete instantiation in stored 'in-place' - in 'bits_t'. -bits_t contains sufficient space to fit the largest of the instantiated objects. - -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 -implementation. Most notably, it does not take a variable number of template parameters but a single parameter defining the type enumeration. As -such it can be used more effectively in generic code. - -The Types parameter specifies the set of allowable types. It models MPL Random Access Container -*/ - -template // models MPL Random Access Container -class variant { - // size in bytes of the largest type in Types - static const std::size_t MAX_SIZE = mpl::fold, mpl::max > >::type::value; - static const std::size_t NUM_TYPES = mpl::size::value; -public: - using types_t = Types; - - using base_t = struct { char data[MAX_SIZE]; }; // empty space equal to the size of the largest type in Types - - // Default constructor - default construct the first type - variant() : _index(0) { new(&_bits) typename mpl::at_c::type(); } - virtual ~variant() { apply_operation(*this, detail::destructor_op()); } - - // Throws std::bad_cast if T is not in Types - template explicit variant(const T& obj){ _index=type_id(); if (_index==NUM_TYPES) throw std::bad_cast(); detail::copy_construct_in_place(obj, _bits); } - - template explicit variant(const variant& obj) : _index(apply_operation(obj,detail::type_to_index_fn())) { - if (_index==NUM_TYPES) throw std::bad_cast(); - apply_operation(obj, detail::copy_construct_in_place_fn(_bits)); - } - - // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call - template explicit variant(T& obj, bool do_swap); - - template variant& operator=(const T& obj) { variant tmp(obj); swap(*this,tmp); return *this; } - variant& operator=(const variant& v) { variant tmp(v ); swap(*this,tmp); return *this; } - - variant(const variant& v) : _index(v._index) { apply_operation(v, detail::copy_construct_in_place_fn(_bits)); } - template void move_in(T& obj) { variant tmp(obj, true); swap(*this,tmp); } - - template friend bool operator==(const variant& x, const variant& y); - template friend bool operator!=(const variant& x, const variant& y); - - template static bool has_type() { return type_id()!=NUM_TYPES; } - - template const T& _dynamic_cast() const { if (!current_type_is()) throw std::bad_cast(); return *gil_reinterpret_cast_c(&_bits); } - template T& _dynamic_cast() { if (!current_type_is()) throw std::bad_cast(); return *gil_reinterpret_cast < T*>(&_bits); } - - template bool current_type_is() const { return type_id()==_index; } - - base_t bits() const { return _bits; } - std::size_t index() const { return _index; } - -private: - template static std::size_t type_id() { return detail::type_to_index::value; } - - template friend void swap(variant& x, variant& y); - template friend typename UnaryOp::result_type apply_operation(variant& var, UnaryOp op); - template friend typename UnaryOp::result_type apply_operation(const variant& var, UnaryOp op); - template friend typename BinaryOp::result_type apply_operation(const variant& arg1, const variant& arg2, BinaryOp op); - - base_t _bits; - std::size_t _index; -}; - -namespace detail { - - template - void copy_construct_in_place(const T& t, Bits& bits) { - T& b=*gil_reinterpret_cast(&bits); - new(&b)T(t); // default-construct - } - - template - struct copy_construct_in_place_fn { - using result_type = void; - Bits& _dst; - copy_construct_in_place_fn(Bits& dst) : _dst(dst) {} - - template void operator()(const T& src) const { copy_construct_in_place(src,_dst); } - }; - - template - struct equal_to_fn { - const Bits& _dst; - equal_to_fn(const Bits& dst) : _dst(dst) {} - - using result_type = bool; - template result_type operator()(const T& x) const { - return x==*gil_reinterpret_cast_c(&_dst); - } - }; - - template - struct type_to_index_fn { - using result_type = std::size_t; - - template result_type operator()(const T&) const { return detail::type_to_index::value; } - }; -} - -// When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call -template -template variant::variant(T& obj, bool do_swap) { - _index=type_id(); - if (_index==NUM_TYPES) throw std::bad_cast(); - - if (do_swap) { - new(&_bits) T(); // default construct - swap(obj, *gil_reinterpret_cast(&_bits)); - } else - detail::copy_construct_in_place(const_cast(obj), _bits); -} - -template -void swap(variant& x, variant& y) { - std::swap(x._bits,y._bits); - std::swap(x._index, y._index); -} - -template -inline bool operator==(const variant& x, const variant& y) { - return x._index==y._index && apply_operation(x,detail::equal_to_fn::base_t>(y._bits)); -} - -template -inline bool operator!=(const variant& x, const variant& y) { - return !(x==y); -} - -} } // namespace boost::gil - -#endif diff --git a/include/boost/gil/io/dynamic_io_new.hpp b/include/boost/gil/io/dynamic_io_new.hpp index 93ee9c8d7b..7c66ae7fd2 100644 --- a/include/boost/gil/io/dynamic_io_new.hpp +++ b/include/boost/gil/io/dynamic_io_new.hpp @@ -25,7 +25,7 @@ struct construct_matched_t { static bool apply(any_image& im,Pred pred) { if (pred.template apply::type>()) { typename mpl::at_c::type x; - im.move_in(x); + im = std::move(x); return true; } else return construct_matched_t::apply(im,pred); }