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 59 : 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 59 : detail::get_key_type<T>>();
48 59 : auto const ps = find_service_impl(ti);
49 59 : if(ps)
50 0 : detail::throw_invalid_argument(
51 : "service exists");
52 59 : return detail::downcast<T&>(
53 : make_service_impl(ti,
54 118 : std::unique_ptr<service>(
55 59 : new T(*this, std::forward<
56 176 : Args>(args)...))));
57 : }
58 :
59 : template<class T>
60 : T*
61 1094 : context::
62 : find_service() const noexcept
63 : {
64 : auto const ti = detail::get_type_index<
65 1094 : detail::get_key_type<T>>();
66 1094 : auto const ps = find_service_impl(ti);
67 1094 : if(! ps)
68 0 : return nullptr;
69 1094 : 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 1093 : context::
83 : get_service() const
84 : {
85 1093 : auto ps = find_service<T>();
86 1093 : if(! ps)
87 0 : detail::throw_invalid_argument(
88 : "service not found");
89 1093 : return *ps;
90 : }
91 :
92 : } // http_proto
93 : } // boost
94 :
95 : #endif
|