Line data Source code
1 : // 2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 3 : // 4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 : // 7 : // Official repository: https://github.com/CPPAlliance/http_proto 8 : // 9 : 10 : #ifndef BOOST_HTTP_PROTO_IMPL_CONTEXT_HPP 11 : #define BOOST_HTTP_PROTO_IMPL_CONTEXT_HPP 12 : 13 : #include <boost/http_proto/detail/except.hpp> 14 : #include <boost/mp11/utility.hpp> 15 : #include <utility> 16 : 17 : namespace boost { 18 : namespace http_proto { 19 : 20 : namespace detail { 21 : 22 : template<class T> 23 : using get_key_impl = 24 : typename T::key_type; 25 : 26 : template<class T> 27 : using get_key_type = 28 : mp11::mp_eval_or<T, get_key_impl, T>; 29 : 30 : } // detail 31 : 32 : //------------------------------------------------ 33 : 34 : template<class T, class... Args> 35 : T& 36 7 : context:: 37 : make_service( 38 : Args&&... args) 39 : { 40 : static_assert( 41 : std::is_base_of<service, T>::value, 42 : "Type requirements not met."); 43 : 44 : auto const ti = detail::get_type_index< 45 7 : detail::get_key_type<T>>(); 46 7 : auto const ps = find_service_impl(ti); 47 7 : if(ps) 48 0 : detail::throw_invalid_argument( 49 : "service exists"); 50 14 : return static_cast<T&>( 51 : make_service_impl(ti, 52 : std::unique_ptr<service>( 53 7 : new T(*this, std::forward< 54 21 : Args>(args)...)))); 55 : } 56 : 57 : template<class T> 58 : T* 59 736 : context:: 60 : find_service() const noexcept 61 : { 62 : auto const ti = detail::get_type_index< 63 736 : detail::get_key_type<T>>(); 64 736 : auto const ps = find_service_impl(ti); 65 736 : if(! ps) 66 0 : return nullptr; 67 736 : return dynamic_cast<T*>(ps); 68 : } 69 : 70 : template<class T> 71 : bool 72 : context:: 73 : has_service() const noexcept 74 : { 75 : return find_service<T>() != nullptr; 76 : } 77 : 78 : template<class T> 79 : T& 80 736 : context:: 81 : get_service() const 82 : { 83 736 : auto ps = find_service<T>(); 84 736 : if(! ps) 85 0 : detail::throw_invalid_argument( 86 : "service not found"); 87 736 : return *ps; 88 : } 89 : 90 : } // http_proto 91 : } // boost 92 : 93 : #endif