/* Copyright 2016-2017 Joaquin M Lopez Munoz. * 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) * * See http://www.boost.org/libs/poly_collection for library home page. */ #ifndef BOOST_POLY_COLLECTION_DETAIL_ANY_MODEL_HPP #define BOOST_POLY_COLLECTION_DETAIL_ANY_MODEL_HPP #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost{ namespace poly_collection{ namespace detail{ /* model for any_collection */ template struct any_model; /* Refine is_acceptable to cover type_erasure::any classes whose assignment * operator won't compile. */ template struct is_acceptable< type_erasure::any,any_model, typename std::enable_if< !type_erasure::is_relaxed::value&& !type_erasure::is_subconcept,Concept2>::value&& !type_erasure::is_subconcept< type_erasure::assignable, Concept2>::value >::type >:std::false_type{}; /* is_terminal defined out-class to allow for partial specialization */ template using any_model_enable_if_has_typeid_=typename std::enable_if< type_erasure::is_subconcept< type_erasure::typeid_::type>, Concept >::value >::type*; template struct any_model_is_terminal:std::true_type{}; template struct any_model_is_terminal< type_erasure::any,any_model_enable_if_has_typeid_ >:std::false_type{}; /* used for make_value_type */ template struct any_model_make_reference { static T& apply(Q& x){return x;} }; template struct any_model { using value_type=type_erasure::any< typename std::conditional< type_erasure::is_subconcept,Concept>::value, Concept, mpl::vector2> >::type, type_erasure::_self& >; template using is_subtype=std::true_type; /* can't compile-time check concept * compliance */ template using is_terminal=any_model_is_terminal; template static const std::type_info& subtypeid(const T&){return typeid(T);} template< typename Concept2,typename T, any_model_enable_if_has_typeid_ =nullptr > static const std::type_info& subtypeid( const type_erasure::any& a) { return type_erasure::typeid_of(a); } template static void* subaddress(T& x){return boost::addressof(x);} template static const void* subaddress(const T& x){return boost::addressof(x);} template< typename Concept2,typename T, any_model_enable_if_has_typeid_ =nullptr > static void* subaddress(type_erasure::any& a) { return type_erasure::any_cast(&a); } template< typename Concept2,typename T, any_model_enable_if_has_typeid_ =nullptr > static const void* subaddress(const type_erasure::any& a) { return type_erasure::any_cast(&a); } using base_iterator=any_iterator; using const_base_iterator=any_iterator; using base_sentinel=value_type*; using const_base_sentinel=const value_type*; template using iterator=Concrete*; template using const_iterator=const Concrete*; using segment_backend=detail::segment_backend; template using segment_backend_implementation=split_segment< any_model, Concrete, typename std::allocator_traits:: template rebind_alloc >; using segment_backend_unique_ptr= typename segment_backend::segment_backend_unique_ptr; static base_iterator nonconst_iterator(const_base_iterator it) { return base_iterator{ const_cast(static_cast(it))}; } template static iterator nonconst_iterator(const_iterator it) { return const_cast>(it); } template static segment_backend_unique_ptr make(const Allocator& al) { return segment_backend_implementation::new_(al,al); } private: template friend class split_segment; template static value_type make_value_type(Concrete& x){return value_type{x};} template static value_type make_value_type(type_erasure::any& x) { /* I don't pretend to understand what's going on here, see * https://lists.boost.org/boost-users/2017/05/87556.php */ using namespace boost::type_erasure; using ref_type=any; using make_ref=any_model_make_reference<_self,ref_type>; using concept_=typename concept_of::type; auto b=make_binding>>(); return {call(binding{b},make_ref{},x),binding{b}}; } }; } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif