Browse Source

delegate: deduction guidelines

Michele Caini 7 years ago
parent
commit
78f2267b06
2 changed files with 85 additions and 0 deletions
  1. 63 0
      src/entt/signal/delegate.hpp
  2. 22 0
      test/entt/signal/delegate.cpp

+ 63 - 0
src/entt/signal/delegate.hpp

@@ -11,6 +11,40 @@
 namespace entt {
 
 
+/**
+ * @cond TURN_OFF_DOXYGEN
+ * Internal details not to be documented.
+ */
+
+
+namespace internal {
+
+
+template<typename Ret, typename... Args>
+auto to_function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...);
+
+
+template<typename Class, typename Ret, typename... Args>
+auto to_function_pointer(Ret(Class:: *)(Args...)) -> Ret(*)(Args...);
+
+
+template<typename Class, typename Ret, typename... Args>
+auto to_function_pointer(Ret(Class:: *)(Args...) const) -> Ret(*)(Args...);
+
+
+template<auto Func>
+using function_type = std::remove_pointer_t<decltype(to_function_pointer(Func))>;
+
+
+}
+
+
+/**
+ * Internal details not to be documented.
+ * @endcond TURN_OFF_DOXYGEN
+ */
+
+
 /*! @brief Used to wrap a function or a member function of a specified type. */
 template<auto>
 struct connect_arg_t {};
@@ -60,6 +94,9 @@ class delegate<Ret(Args...)> final {
     }
 
 public:
+    /*! @brief Function type of the delegate. */
+    using function_type = Ret(Args...);
+
     /*! @brief Default constructor. */
     delegate() ENTT_NOEXCEPT
         : stub{}
@@ -194,6 +231,32 @@ bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)>
 }
 
 
+/**
+ * @brief Deduction guideline.
+ *
+ * It allows to deduce the function type of the delegate directly from the
+ * function provided to the constructor.
+ *
+ * @tparam Function A valid free function pointer.
+ */
+template<auto Function>
+delegate(connect_arg_t<Function>) ENTT_NOEXCEPT -> delegate<internal::function_type<Function>>;
+
+
+/**
+
+ * @brief Deduction guideline.
+ *
+ * It allows to deduce the function type of the delegate directly from the
+ * member function provided to the constructor.
+ *
+ * @tparam Member Member function to connect to the delegate.
+ * @tparam Class Type of class to which the member function belongs.
+ */
+template<auto Member, typename Class>
+delegate(connect_arg_t<Member>, Class *) ENTT_NOEXCEPT -> delegate<internal::function_type<Member>>;
+
+
 }
 
 

+ 22 - 0
test/entt/signal/delegate.cpp

@@ -87,3 +87,25 @@ TEST(Delegate, Constructors) {
     ASSERT_TRUE(func);
     ASSERT_TRUE(member);
 }
+
+TEST(Delegate, DeducedGuidelines) {
+    const_nonconst_noexcept functor;
+
+    entt::delegate func_deduced{entt::connect_arg<&delegate_function>};
+    entt::delegate member_f_deduced{entt::connect_arg<&const_nonconst_noexcept::f>, &functor};
+    entt::delegate member_g_deduced{entt::connect_arg<&const_nonconst_noexcept::g>, &functor};
+    entt::delegate member_h_deduced{entt::connect_arg<&const_nonconst_noexcept::h>, &functor};
+    entt::delegate member_i_deduced{entt::connect_arg<&const_nonconst_noexcept::i>, &functor};
+
+    static_assert(std::is_same_v<typename decltype(func_deduced)::function_type, int(const int &)>);
+    static_assert(std::is_same_v<typename decltype(member_f_deduced)::function_type, void()>);
+    static_assert(std::is_same_v<typename decltype(member_g_deduced)::function_type, void()>);
+    static_assert(std::is_same_v<typename decltype(member_h_deduced)::function_type, void()>);
+    static_assert(std::is_same_v<typename decltype(member_i_deduced)::function_type, void()>);
+
+    ASSERT_TRUE(func_deduced);
+    ASSERT_TRUE(member_f_deduced);
+    ASSERT_TRUE(member_g_deduced);
+    ASSERT_TRUE(member_h_deduced);
+    ASSERT_TRUE(member_i_deduced);
+}