slot: add friended get function

Similar to bus, infrequently sdbusplus classes need to be able to gain
access to the slot pointer to pass along to other calls.  Create a
`slot_friend` class which provides a static method to gain access to the
underlying pointer.

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I371b62ca7b82c9c93e5abb71cdab4abda713aa5e
diff --git a/include/sdbusplus/message.hpp b/include/sdbusplus/message.hpp
index 007880c..ea9869c 100644
--- a/include/sdbusplus/message.hpp
+++ b/include/sdbusplus/message.hpp
@@ -66,7 +66,7 @@
 /** @class message
  *  @brief Provides C++ bindings to the sd_bus_message_* class functions.
  */
-class message
+class message : private sdbusplus::slot::details::slot_friend
 {
     /* Define all of the basic class operations:
      *     Allowed:
@@ -427,35 +427,28 @@
         {
             throw exception::SdBusError(-r, "sd_bus_call_async");
         }
-
-        // Generally, slot_t expects to act like a RAII wrapper but it doesn't
-        // allow direct access to the underlying pointer.  We still have some
-        // updates we need to make to the slot after it is saved away in the
-        // RAII wrapper, so we need to explicitly make a copy of the pointer for
-        // later use.
-        sd_bus_slot* slot_saved = slot;
         slot_t ret(std::move(slot));
 
         if constexpr (std::is_pointer_v<CbT>)
         {
-            _intf->sd_bus_slot_set_userdata(slot_saved,
+            _intf->sd_bus_slot_set_userdata(get_slotp(ret),
                                             reinterpret_cast<void*>(cb));
         }
         else if constexpr (std::is_function_v<CbT>)
         {
-            _intf->sd_bus_slot_set_userdata(slot_saved,
+            _intf->sd_bus_slot_set_userdata(get_slotp(ret),
                                             reinterpret_cast<void*>(&cb));
         }
         else
         {
             r = _intf->sd_bus_slot_set_destroy_callback(
-                slot_saved, details::call_async_del<CbT>);
+                get_slotp(ret), details::call_async_del<CbT>);
             if (r < 0)
             {
                 throw exception::SdBusError(-r,
                                             "sd_bus_slot_set_destroy_callback");
             }
-            _intf->sd_bus_slot_set_userdata(slot_saved,
+            _intf->sd_bus_slot_set_userdata(get_slotp(ret),
                                             new CbT(std::forward<Cb>(cb)));
         }
         return ret;
diff --git a/include/sdbusplus/slot.hpp b/include/sdbusplus/slot.hpp
index 7144281..10a1d0d 100644
--- a/include/sdbusplus/slot.hpp
+++ b/include/sdbusplus/slot.hpp
@@ -27,6 +27,8 @@
 
 using slot = std::unique_ptr<sd_bus_slot, SlotDeleter>;
 
+struct slot_friend;
+
 } // namespace details
 
 /** @class slot
@@ -81,10 +83,33 @@
         return bool(_slot);
     }
 
+    friend struct details::slot_friend;
+
   private:
+    slotp_t get() noexcept
+    {
+        return _slot.get();
+    }
     details::slot _slot;
 };
 
+namespace details
+{
+
+// Some sdbusplus classes need to be able to pass the underlying slot pointer
+// along to sd_bus calls, but we don't want to make it available for everyone.
+// Define a class which can be inherited explicitly (intended for internal users
+// only) to get the underlying bus pointer.
+struct slot_friend
+{
+    static slotp_t get_slotp(sdbusplus::slot::slot& s) noexcept
+    {
+        return s.get();
+    }
+};
+
+} // namespace details
+
 } // namespace slot
 
 using slot_t = slot::slot;