1 #pragma once 2 3 #include <sdbusplus/async/proxy.hpp> 4 5 namespace sdbusplus::async 6 { 7 8 namespace client 9 { 10 11 namespace details 12 { 13 struct client_context_friend; 14 } 15 16 /** An aggregation class of sdbusplus::async::proxy-based client types. 17 * 18 * The resulting class acts as a union of all Types from the template 19 * arguments. 20 * 21 * Like a `proxy`, the class only becomes functional once the service and 22 * path are populated. 23 */ 24 template <bool S, bool P, bool Preserved, 25 template <typename, typename> typename... Types> 26 class client : 27 public context_ref, 28 public Types<client<S, P, Preserved, Types...>, 29 sdbusplus::async::proxy_ns::proxy<S, P, false, Preserved>>... 30 { 31 public: 32 using Self = client<S, P, Preserved, Types...>; 33 using Proxy = sdbusplus::async::proxy_ns::proxy<S, P, false, Preserved>; 34 friend details::client_context_friend; 35 36 private: 37 Proxy proxy{}; 38 39 public: 40 constexpr client() = delete; 41 /* Delete default constructor if Service or Path have been provided. */ 42 explicit client(sdbusplus::async::context& ctx) 43 requires(S || P) 44 = delete; 45 /* Default (empty) constructor only when Service and Path are missing. */ client(sdbusplus::async::context & ctx)46 explicit client(sdbusplus::async::context& ctx) 47 requires(!S && !P) 48 : context_ref(ctx), Types<Self, Proxy>(Proxy{})... 49 {} 50 51 /* Conversion constructor for a non-empty (Service and/or Path) proxy. */ client(sdbusplus::async::context & ctx,Proxy p)52 explicit client(sdbusplus::async::context& ctx, Proxy p) 53 requires(S || P) 54 : context_ref(ctx), Types<Self, Proxy>(p)..., proxy(p) 55 {} 56 57 /* Convert a non-Service instance to a Service instance. */ service(auto & s) const58 auto service(auto& s) const noexcept 59 requires(!S) 60 { 61 return client<true, P, Preserved, Types...>(ctx, proxy.service(s)); 62 } 63 64 /* Convert a non-Path instance to a Path instance. */ path(auto & p) const65 auto path(auto& p) const noexcept 66 requires(!P) 67 { 68 return client<S, true, Preserved, Types...>(ctx, proxy.path(p)); 69 } 70 71 /* Convert client into a Preserved Proxy. */ preserve() const72 auto preserve() const noexcept 73 requires(!Preserved) 74 { 75 return client<S, P, true, Types...>(ctx, proxy.preserve()); 76 } 77 }; 78 79 } // namespace client 80 81 /** A non-Preserved client alias. 82 * 83 * This holds Service/Path in string-views, which must exist longer than 84 * the lifetime of this client_t. 85 */ 86 template <template <typename, typename> typename... Types> 87 using client_t = client::client<false, false, false, Types...>; 88 /** A Preserved client alias. 89 * 90 * This holds Service/Path in strings, which thus have lifetimes that are 91 * the same as the client itself. 92 */ 93 template <template <typename, typename> typename... Types> 94 using client_preserved_t = client::client<false, false, true, Types...>; 95 96 namespace client::details 97 { 98 /* Indirect so that the generated Types can access the client_t's context. 99 * 100 * If P2893 gets into C++26 we could eliminate this because we can set all 101 * the Types as friends directly. 102 */ 103 struct client_context_friend 104 { 105 template <typename Client, typename Self> contextsdbusplus::async::client::details::client_context_friend106 static sdbusplus::async::context& context(Self* self) 107 { 108 return static_cast<Client*>(self)->ctx; 109 } 110 }; 111 } // namespace client::details 112 113 } // namespace sdbusplus::async 114