delegate works now also with move only types (close #272)
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
- iterator based each with a couple of iterators passed from outside (use bitmask + has)
|
||||
* stable component handle that isn't affected by reallocations
|
||||
* multi component registry::remove and some others?
|
||||
* can I use opaque connection also for the emitter?
|
||||
* built-in support for dual (or N-) buffering
|
||||
|
||||
TODO
|
||||
|
||||
@@ -101,16 +101,16 @@ class delegate;
|
||||
*/
|
||||
template<typename Ret, typename... Args>
|
||||
class delegate<Ret(Args...)> {
|
||||
using proto_fn_type = Ret(const void *, std::tuple<Args...>);
|
||||
using proto_fn_type = Ret(const void *, std::tuple<Args &&...>);
|
||||
|
||||
template<auto Function, std::size_t... Index>
|
||||
void connect(std::index_sequence<Index...>) ENTT_NOEXCEPT {
|
||||
data = nullptr;
|
||||
|
||||
fn = [](const void *, std::tuple<Args...> args) -> Ret {
|
||||
fn = [](const void *, std::tuple<Args &&...> args) -> Ret {
|
||||
// Ret(...) makes void(...) eat the return values to avoid errors
|
||||
static_assert(std::is_invocable_r_v<Ret, decltype(Function), std::tuple_element_t<Index, std::tuple<Args...>>...>);
|
||||
// Ret(...) allows void(...) to eat return values and avoid errors
|
||||
return Ret(std::invoke(Function, std::get<Index>(args)...));
|
||||
return Ret(std::invoke(Function, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class delegate<Ret(Args...)> {
|
||||
void connect(Type *value_or_instance, std::index_sequence<Index...>) ENTT_NOEXCEPT {
|
||||
data = value_or_instance;
|
||||
|
||||
fn = [](const void *payload, std::tuple<Args...> args) -> Ret {
|
||||
fn = [](const void *payload, std::tuple<Args &&...> args) -> Ret {
|
||||
Type *curr = nullptr;
|
||||
|
||||
if constexpr(std::is_const_v<Type>) {
|
||||
@@ -127,9 +127,9 @@ class delegate<Ret(Args...)> {
|
||||
curr = static_cast<Type *>(const_cast<void *>(payload));
|
||||
}
|
||||
|
||||
// Ret(...) makes void(...) eat the return values to avoid errors
|
||||
static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, std::tuple_element_t<Index, std::tuple<Args...>>...>);
|
||||
// Ret(...) allows void(...) to eat return values and avoid errors
|
||||
return Ret(std::invoke(Candidate, curr, std::get<Index>(args)...));
|
||||
return Ret(std::invoke(Candidate, curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
*/
|
||||
Ret operator()(Args... args) const {
|
||||
ENTT_ASSERT(fn);
|
||||
return fn(data, std::forward_as_tuple(args...));
|
||||
return fn(data, std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <memory>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/signal/delegate.hpp>
|
||||
|
||||
@@ -9,6 +10,14 @@ int curried_function(const int *i, int j) {
|
||||
return *i+j;
|
||||
}
|
||||
|
||||
int non_const_reference(int &i) {
|
||||
return i *= i;
|
||||
}
|
||||
|
||||
int move_only_type(std::unique_ptr<int> ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
struct delegate_functor {
|
||||
int operator()(int i) {
|
||||
return i+i;
|
||||
@@ -235,6 +244,24 @@ TEST(Delegate, ConstInstance) {
|
||||
ASSERT_EQ(delegate, entt::delegate<int(int)>{});
|
||||
}
|
||||
|
||||
TEST(Delegate, NonConstReference) {
|
||||
entt::delegate<int(int &)> delegate;
|
||||
delegate.connect<&non_const_reference>();
|
||||
int value = 3;
|
||||
|
||||
ASSERT_EQ(delegate(value), value);
|
||||
ASSERT_EQ(value, 9);
|
||||
}
|
||||
|
||||
TEST(Delegate, MoveOnlyType) {
|
||||
entt::delegate<int(std::unique_ptr<int>)> delegate;
|
||||
auto ptr = std::make_unique<int>(3);
|
||||
delegate.connect<&move_only_type>();
|
||||
|
||||
ASSERT_EQ(delegate(std::move(ptr)), 3);
|
||||
ASSERT_FALSE(ptr);
|
||||
}
|
||||
|
||||
TEST(Delegate, CurriedFunction) {
|
||||
entt::delegate<int(int)> delegate;
|
||||
const auto value = 3;
|
||||
|
||||
Reference in New Issue
Block a user