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/http_proto/detail/type_index.hpp> 15 : 16 : #include <boost/mp11/utility.hpp> 17 : #include <utility> 18 : 19 : namespace boost { 20 : namespace http_proto { 21 : 22 : namespace detail { 23 : 24 : template<class T> 25 : using get_key_impl = 26 : typename T::key_type; 27 : 28 : template<class T> 29 : using get_key_type = 30 : mp11::mp_eval_or<T, get_key_impl, T>; 31 : 32 : } // detail 33 : 34 : //------------------------------------------------ 35 : 36 : template<class T, class... Args> 37 : T& 38 32 : context:: 39 : make_service( 40 : Args&&... args) 41 : { 42 : static_assert( 43 : std::is_base_of<service, T>::value, 44 : "Type requirements not met."); 45 : 46 : auto const ti = detail::get_type_index< 47 32 : detail::get_key_type<T>>(); 48 32 : auto const ps = find_service_impl(ti); 49 32 : if(ps) 50 0 : detail::throw_invalid_argument( 51 : "service exists"); 52 64 : return detail::downcast<T&>( 53 : make_service_impl(ti, 54 1 : std::unique_ptr<service>( 55 32 : new T(*this, std::forward< 56 95 : Args>(args)...)))); 57 : } 58 : 59 : template<class T> 60 : T* 61 792 : context:: 62 : find_service() const noexcept 63 : { 64 : auto const ti = detail::get_type_index< 65 792 : detail::get_key_type<T>>(); 66 792 : auto const ps = find_service_impl(ti); 67 792 : if(! ps) 68 0 : return nullptr; 69 792 : return detail::downcast<T*>(ps); 70 : } 71 : 72 : template<class T> 73 : bool 74 : context:: 75 : has_service() const noexcept 76 : { 77 : return find_service<T>() != nullptr; 78 : } 79 : 80 : template<class T> 81 : T& 82 791 : context:: 83 : get_service() const 84 : { 85 791 : auto ps = find_service<T>(); 86 791 : if(! ps) 87 0 : detail::throw_invalid_argument( 88 : "service not found"); 89 791 : return *ps; 90 : } 91 : 92 : } // http_proto 93 : } // boost 94 : 95 : #endif