Skip to content

Commit

Permalink
Move direction semantics from dispatches to conventions (#125)
Browse files Browse the repository at this point in the history
* Move direction semantics from dispatches to conventions

* Resolve comments

* Reorder macros

* Resolve comments
  • Loading branch information
mingxwa authored Jul 3, 2024
1 parent 9636e15 commit 26483ac
Show file tree
Hide file tree
Showing 7 changed files with 444 additions and 608 deletions.
982 changes: 404 additions & 578 deletions proxy.h

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion tests/proxy_creation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace {

struct SboObserver {
public:
static constexpr bool is_direct = true;
template <class T>
constexpr explicit SboObserver(std::in_place_type_t<pro::details::inplace_ptr<T>>)
: SboEnabled(true), AllocatorAllocatesForItself(false) {}
Expand Down
11 changes: 5 additions & 6 deletions tests/proxy_dispatch_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ PRO_DEF_OPERATOR_DISPATCH(OpPipe, "|");
PRO_DEF_OPERATOR_DISPATCH(OpCaret, "^");
PRO_DEF_OPERATOR_DISPATCH(OpLeftShift, "<<");
PRO_DEF_OPERATOR_DISPATCH(OpRightShift, ">>");
PRO_DEF_DIRECT_OPERATOR_DISPATCH(DirectOpPlusAssignment, "+=");
PRO_DEF_OPERATOR_DISPATCH(OpPlusAssignment, "+=");
PRO_DEF_OPERATOR_DISPATCH(OpMinusAssignment, "-=");
PRO_DEF_OPERATOR_DISPATCH(OpMultiplicationAssignment, "*=");
Expand All @@ -48,7 +47,7 @@ PRO_DEF_OPERATOR_DISPATCH(OpBitwiseXorAssignment, "^=");
PRO_DEF_OPERATOR_DISPATCH(OpLeftShiftAssignment, "<<=");
PRO_DEF_OPERATOR_DISPATCH(OpRightShiftAssignment, ">>=");
PRO_DEF_OPERATOR_DISPATCH(OpComma, ",");
PRO_DEF_DIRECT_OPERATOR_DISPATCH(OpPtrToMem, "->*");
PRO_DEF_OPERATOR_DISPATCH(OpPtrToMem, "->*");
PRO_DEF_OPERATOR_DISPATCH(OpParentheses, "()");
PRO_DEF_OPERATOR_DISPATCH(OpBrackets, "[]");

Expand Down Expand Up @@ -85,7 +84,7 @@ PRO_DEF_RHS_OPERATOR_DISPATCH(RhsOpPtrToMem, "->*");

PRO_DEF_CONVERSION_DISPATCH(ConvertToInt, int);
template <class F>
PRO_DEF_DIRECT_CONVERSION_DISPATCH(ConvertToBase, pro::proxy<F>);
PRO_DEF_CONVERSION_DISPATCH(ConvertToBase, pro::proxy<F>);

struct CommaTester {
public:
Expand Down Expand Up @@ -289,7 +288,7 @@ TEST(ProxyDispatchTests, TestOpRightShift) {
TEST(ProxyDispatchTests, TestOpPlusAssignment) {
struct TestFacade : pro::facade_builder
::add_convention<OpPlusAssignment, void(int val)>
::add_convention<DirectOpPlusAssignment, void(int val)>
::add_direct_convention<OpPlusAssignment, void(int val)>
::build {};
int v[3] = {12, 0, 7};
pro::proxy<TestFacade> p = v;
Expand Down Expand Up @@ -377,7 +376,7 @@ TEST(ProxyDispatchTests, TestOpPtrToMem) {
struct Base2 { double x; };
struct Derived1 : Base1 { int x; };
struct Derived2 : Base2, Base1 { int d; };
struct TestFacade : pro::facade_builder::add_convention<OpPtrToMem, int&(int Base1::* ptm)>::build {};
struct TestFacade : pro::facade_builder::add_direct_convention<OpPtrToMem, int&(int Base1::* ptm)>::build {};
Derived1 v1{};
Derived2 v2{};
pro::proxy<TestFacade> p1 = &v1, p2 = &v2;
Expand Down Expand Up @@ -668,7 +667,7 @@ TEST(ProxyDispatchTests, TestDirectConversion) {
struct TestFacade : pro::facade_builder
::add_facade<TestFacadeBase>
::add_convention<OpPlusAssignment, void(int val)>
::add_convention<ConvertToBase<TestFacadeBase>, pro::proxy<TestFacadeBase>() &&>
::add_direct_convention<ConvertToBase<TestFacadeBase>, pro::proxy<TestFacadeBase>() &&>
::build {};
pro::proxy<TestFacade> p1 = std::make_unique<int>(123);
*p1 += 3;
Expand Down
29 changes: 25 additions & 4 deletions tests/proxy_invocation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ PRO_DEF_FREE_DISPATCH(FreeAppend, AppendImpl, Append);
template <class T>
struct Container : pro::facade_builder
::add_facade<Iterable<T>>
::template add_convention<FreeAppend, pro::proxy<Container<T>>(T)>
::template add_convention<FreeAppend, pro::proxy<Container<T>>(T) const&>
::build {};

PRO_DEF_MEM_DISPATCH(MemAtWeak, at, at, NotImplemented);
Expand Down Expand Up @@ -98,18 +98,18 @@ template <class F, class T>
auto GetWeakImpl(const std::shared_ptr<T>& p) { return pro::make_proxy<Weak<F>, std::weak_ptr<T>>(p); }

template <class F>
PRO_DEF_DIRECT_FREE_DISPATCH(FreeGetWeak, GetWeakImpl<F>, GetWeak, std::nullptr_t);
PRO_DEF_FREE_DISPATCH(FreeGetWeak, GetWeakImpl<F>, GetWeak, std::nullptr_t);

struct SharedStringable : pro::facade_builder
::add_facade<utils::spec::Stringable>
::add_convention<FreeGetWeak<SharedStringable>, pro::proxy<Weak<SharedStringable>>() const&>
::add_direct_convention<FreeGetWeak<SharedStringable>, pro::proxy<Weak<SharedStringable>>() const&>
::build {};

} // namespace spec

template <class F, bool NE, class... Args>
concept CallableFacade =
requires(const pro::proxy<F> p, Args... args) {
requires(pro::proxy<F> p, Args... args) {
{ (*p)(std::forward<Args>(args)...) };
typename std::enable_if_t<NE == noexcept((*p)(std::forward<Args>(args)...))>;
};
Expand Down Expand Up @@ -299,3 +299,24 @@ TEST(ProxyInvocationTests, TestObserverDispatch) {
ASSERT_FALSE(GetWeak(p).has_value());
ASSERT_EQ(ToString(*p), "123");
}

TEST(ProxyInvocationTests, TestQualifiedConvention) {
struct TestFacade : pro::facade_builder
::add_convention<spec::OpCall, int()&, int() const&, int()&& noexcept, int() const&&>
::build {};

struct TestCallable {
int operator()()& noexcept { return 0; }
int operator()() const& noexcept { return 1; }
int operator()() && noexcept { return 2; }
int operator()() const&& noexcept { return 3; }
};

pro::proxy<TestFacade> p = pro::make_proxy<TestFacade, TestCallable>();
static_assert(!noexcept((*p)()));
static_assert(noexcept((*std::move(p))()));
ASSERT_EQ((*p)(), 0);
ASSERT_EQ((*std::as_const(p))(), 1);
ASSERT_EQ((*std::move(p))(), 2);
ASSERT_EQ((*std::move(std::as_const(p)))(), 3);
}
8 changes: 2 additions & 6 deletions tests/proxy_reflection_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ namespace {

class RttiReflection {
public:
static constexpr bool is_direct = false;

template <class T>
constexpr explicit RttiReflection(std::in_place_type_t<T>)
: type_(typeid(T)) {}
Expand All @@ -24,8 +22,6 @@ class RttiReflection {

struct TraitsReflection {
public:
static constexpr bool is_direct = true;

template <class P>
constexpr explicit TraitsReflection(std::in_place_type_t<P>)
: is_default_constructible_(std::is_default_constructible_v<P>),
Expand Down Expand Up @@ -54,12 +50,12 @@ struct TestTraitsFacade : pro::facade_builder
TEST(ProxyReflectionTests, TestRtti_RawPtr) {
int foo = 123;
pro::proxy<TestRttiFacade> p = &foo;
ASSERT_STREQ(pro::proxy_reflect<RttiReflection>(p).GetName(), typeid(int).name());
ASSERT_STREQ(pro::proxy_reflect<RttiReflection>(p).GetName(), typeid(int*).name());
}

TEST(ProxyReflectionTests, TestRtti_FancyPtr) {
pro::proxy<TestRttiFacade> p = std::make_unique<double>(1.23);
ASSERT_STREQ(pro::proxy_reflect<RttiReflection>(p).GetName(), typeid(double).name());
ASSERT_STREQ(pro::proxy_reflect<RttiReflection>(p).GetName(), typeid(std::unique_ptr<double>).name());
}

TEST(ProxyReflectionTests, TestTraits_RawPtr) {
Expand Down
20 changes: 7 additions & 13 deletions tests/proxy_traits_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ static_assert(std::is_nothrow_assignable_v<pro::proxy<TrivialFacade>, MockFuncti
static_assert(sizeof(pro::proxy<TrivialFacade>) == 2 * sizeof(void*)); // VTABLE should be eliminated, but a placeholder is required

struct ReflectionOfSmallPtr {
static constexpr bool is_direct = true;

template <class P> requires(sizeof(P) <= sizeof(void*))
constexpr ReflectionOfSmallPtr(std::in_place_type_t<P>) {}
};
Expand All @@ -170,8 +168,6 @@ static_assert(pro::proxiable<MockTrivialPtr, RelocatableFacadeWithReflection>);
static_assert(pro::proxiable<MockFunctionPtr, RelocatableFacadeWithReflection>);

struct RuntimeReflection {
static constexpr bool is_direct = true;

template <class P>
explicit RuntimeReflection(std::in_place_type_t<P>) { throw std::runtime_error{"Not supported"}; }
};
Expand All @@ -182,6 +178,7 @@ static_assert(!pro::proxiable<MockTrivialPtr, FacadeWithRuntimeReflection>);

struct FacadeWithTupleLikeConventions {
struct ToStringConvention {
static constexpr bool is_direct = false;
using dispatch_type = utils::spec::FreeToString;
using overload_types = std::tuple<std::string()>;
};
Expand Down Expand Up @@ -308,7 +305,7 @@ struct BadFacade_MissingReflectionTypes {
static_assert(!pro::facade<BadFacade_MissingReflectionTypes>);

struct BadReflection {
static const bool is_direct;
BadReflection() = delete;
};
struct BadFacade_BadReflectionType {
using convention_types = std::tuple<>;
Expand All @@ -321,18 +318,15 @@ struct BadFacade_BadReflectionType {
.destructibility = pro::constraint_level::nothrow,
};
};
static_assert(!pro::facade<BadFacade_BadReflectionType>);
const bool BadReflection::is_direct = true;
static_assert(pro::facade<BadFacade_BadReflectionType>);

PRO_DEF_INDIRECT_MEM_DISPATCH(MemFoo, Foo);
PRO_DEF_INDIRECT_MEM_DISPATCH(MemBar, Bar);
PRO_DEF_DIRECT_MEM_DISPATCH(DirMemFoo, Foo);
PRO_DEF_DIRECT_MEM_DISPATCH(DirMemBar, Bar);
PRO_DEF_MEM_DISPATCH(MemFoo, Foo);
PRO_DEF_MEM_DISPATCH(MemBar, Bar);
struct BigFacade : pro::facade_builder
::add_convention<MemFoo, void(), void(int)>
::add_convention<MemBar, void(), void(int)>
::add_convention<DirMemFoo, void(), void(int)>
::add_convention<DirMemBar, void(), void(int)>
::add_direct_convention<MemFoo, void(), void(int)>
::add_direct_convention<MemBar, void(), void(int)>
::build {};
static_assert(sizeof(pro::proxy<BigFacade>) == 3 * sizeof(void*)); // Accessors should not add paddings

Expand Down
1 change: 1 addition & 0 deletions tests/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class LifetimeTracker {
host_(rhs.host_) {}
~Session() { host_->ops_.emplace_back(id_, LifetimeOperationType::kDestruction); }
const Session* operator->() const { return this; }
const Session& operator*() const { return *this; }
friend std::string to_string(const Session& self) { return "Session " + std::to_string(self.id_); }

private:
Expand Down

0 comments on commit 26483ac

Please sign in to comment.