1 /* Copyright 2016-2018 Joaquin M Lopez Munoz. 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * See http://www.boost.org/libs/poly_collection for library home page. 7 */ 8 9 #ifndef BOOST_POLY_COLLECTION_DETAIL_FUNCTION_MODEL_HPP 10 #define BOOST_POLY_COLLECTION_DETAIL_FUNCTION_MODEL_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/core/addressof.hpp> 17 #include <boost/poly_collection/detail/callable_wrapper.hpp> 18 #include <boost/poly_collection/detail/callable_wrapper_iterator.hpp> 19 #include <boost/poly_collection/detail/is_invocable.hpp> 20 #include <boost/poly_collection/detail/segment_backend.hpp> 21 #include <boost/poly_collection/detail/split_segment.hpp> 22 #include <memory> 23 #include <type_traits> 24 #include <typeinfo> 25 #include <utility> 26 27 namespace boost{ 28 29 namespace poly_collection{ 30 31 namespace detail{ 32 33 /* model for function_collection */ 34 35 template<typename Signature> 36 struct function_model; 37 38 /* is_terminal defined out-class to allow for partial specialization */ 39 40 template<typename T> 41 struct function_model_is_terminal:std::true_type{}; 42 43 template<typename Signature> 44 struct function_model_is_terminal<callable_wrapper<Signature>>: 45 std::false_type{}; 46 47 template<typename R,typename... Args> 48 struct function_model<R(Args...)> 49 { 50 using value_type=callable_wrapper<R(Args...)>; 51 52 template<typename Callable> 53 using is_implementation=is_invocable_r<R,Callable&,Args...>; 54 55 template<typename T> 56 using is_terminal=function_model_is_terminal<T>; 57 58 template<typename T> subtypeidboost::poly_collection::detail::function_model59 static const std::type_info& subtypeid(const T&){return typeid(T);} 60 61 template<typename Signature> subtypeidboost::poly_collection::detail::function_model62 static const std::type_info& subtypeid( 63 const callable_wrapper<Signature>& f) 64 { 65 return f.target_type(); 66 } 67 68 template<typename T> subaddressboost::poly_collection::detail::function_model69 static void* subaddress(T& x){return boost::addressof(x);} 70 71 template<typename T> subaddressboost::poly_collection::detail::function_model72 static const void* subaddress(const T& x){return boost::addressof(x);} 73 74 template<typename Signature> subaddressboost::poly_collection::detail::function_model75 static void* subaddress(callable_wrapper<Signature>& f) 76 { 77 return f.data(); 78 } 79 80 template<typename Signature> subaddressboost::poly_collection::detail::function_model81 static const void* subaddress(const callable_wrapper<Signature>& f) 82 { 83 return f.data(); 84 } 85 86 using base_iterator=callable_wrapper_iterator<value_type>; 87 using const_base_iterator=callable_wrapper_iterator<const value_type>; 88 using base_sentinel=value_type*; 89 using const_base_sentinel=const value_type*; 90 template<typename Callable> 91 using iterator=Callable*; 92 template<typename Callable> 93 using const_iterator=const Callable*; 94 template<typename Allocator> 95 using segment_backend=detail::segment_backend<function_model,Allocator>; 96 template<typename Callable,typename Allocator> 97 using segment_backend_implementation= 98 split_segment<function_model,Callable,Allocator>; 99 nonconst_iteratorboost::poly_collection::detail::function_model100 static base_iterator nonconst_iterator(const_base_iterator it) 101 { 102 return base_iterator{ 103 const_cast<value_type*>(static_cast<const value_type*>(it))}; 104 } 105 106 template<typename T> nonconst_iteratorboost::poly_collection::detail::function_model107 static iterator<T> nonconst_iterator(const_iterator<T> it) 108 { 109 return const_cast<iterator<T>>(it); 110 } 111 112 private: 113 template<typename,typename,typename> 114 friend class split_segment; 115 116 template<typename Callable> make_value_typeboost::poly_collection::detail::function_model117 static value_type make_value_type(Callable& x){return value_type{x};} 118 }; 119 120 } /* namespace poly_collection::detail */ 121 122 } /* namespace poly_collection */ 123 124 } /* namespace boost */ 125 126 #endif 127