Skip to content
This repository was archived by the owner on Jan 29, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class Rectangle {
std::string PrintDrawableToString(pro::proxy<Drawable> p) {
std::stringstream result;
result << "shape = ";
p.Draw(result); // Polymorphic call
result << ", area = " << p.Area(); // Polymorphic call
p->Draw(result); // Polymorphic call
result << ", area = " << p->Area(); // Polymorphic call
return std::move(result).str();
}

Expand All @@ -76,11 +76,11 @@ struct Logger : pro::facade_builder

// Client - Consumer
void MyVerboseFunction(pro::proxy<Logger> logger) {
logger.Log("hello");
logger->Log("hello");
try {
throw std::runtime_error{"runtime error!"};
} catch (const std::exception& e) {
logger.Log("world", e);
logger->Log("world", e);
}
}

Expand Down Expand Up @@ -133,11 +133,11 @@ int main() {
puts("");
};
MyFunction<void(int)> p0{&f};
p0(123); // Prints "f() called. Args: 123:i," (assuming GCC)
(*p0)(123); // Prints "f() called. Args: 123:i," (assuming GCC)
MyMoveOnlyFunction<void(), void(int), void(double)> p1{&f};
p1(); // Prints "f() called. Args:"
p1(456); // Prints "f() called. Args: 456:i,"
p1(1.2); // Prints "f() called. Args: 1.2:d,"
(*p1)(); // Prints "f() called. Args:"
(*p1)(456); // Prints "f() called. Args: 456:i,"
(*p1)(1.2); // Prints "f() called. Args: 1.2:d,"
return 0;
}
```
Expand Down
1,228 changes: 864 additions & 364 deletions proxy.h

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion samples/resource_dictionary/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct Dictionary : pro::facade_builder
} // namespace spec

void demo_print(pro::proxy<spec::Dictionary> dictionary) {
std::cout << dictionary.at(1) << std::endl;
std::cout << dictionary->at(1) << std::endl;
}

int main() {
Expand Down
8 changes: 4 additions & 4 deletions tests/freestanding/proxy_freestanding_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ extern "C" int main() {
std::tuple<int, double> t{11, 22};
pro::proxy<spec::Hashable> p;
p = &i;
if (GetHash(p) != GetHash(i)) {
if (GetHash(*p) != GetHash(i)) {
return 1;
}
p = &d;
if (GetHash(p) != GetHash(d)) {
if (GetHash(*p) != GetHash(d)) {
return 1;
}
p = pro::make_proxy_inplace<spec::Hashable>(s);
if (GetHash(p) != GetHash(s)) {
if (GetHash(*p) != GetHash(s)) {
return 1;
}
p = &t;
if (GetHash(p) != GetDefaultHash()) {
if (GetHash(*p) != GetDefaultHash()) {
return 1;
}
return 0;
Expand Down
61 changes: 31 additions & 30 deletions tests/proxy_creation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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 Expand Up @@ -86,7 +87,7 @@ TEST(ProxyCreationTests, TestMakeProxyInplace_FromValue) {
{
auto p = pro::make_proxy_inplace<spec::TestLargeStringable>(session);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 2");
ASSERT_EQ(ToString(*p), "Session 2");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -101,7 +102,7 @@ TEST(ProxyCreationTests, TestMakeProxyInplace_InPlace) {
{
auto p = pro::make_proxy_inplace<spec::TestLargeStringable, utils::LifetimeTracker::Session>(&tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -116,7 +117,7 @@ TEST(ProxyCreationTests, TestMakeProxyInplace_InPlaceInitializerList) {
{
auto p = pro::make_proxy_inplace<spec::TestLargeStringable, utils::LifetimeTracker::Session>({ 1, 2, 3 }, &tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kInitializerListConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -133,10 +134,10 @@ TEST(ProxyCreationTests, TestMakeProxyInplace_Lifetime_Copy) {
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
auto p2 = p1;
ASSERT_TRUE(p1.has_value());
ASSERT_EQ(ToString(p1), "Session 1");
ASSERT_EQ(ToString(*p1), "Session 1");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p1).SboEnabled);
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -155,7 +156,7 @@ TEST(ProxyCreationTests, TestMakeProxyInplace_Lifetime_Move) {
auto p2 = std::move(p1);
ASSERT_FALSE(p1.has_value());
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kMoveConstruction);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kDestruction);
Expand All @@ -173,7 +174,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_DirectAllocator_FromValue) {
{
auto p = pro::allocate_proxy<spec::TestSmallStringable>(std::allocator<void>{}, session);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 2");
ASSERT_EQ(ToString(*p), "Session 2");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
Expand All @@ -189,7 +190,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_DirectAllocator_InPlace) {
{
auto p = pro::allocate_proxy<spec::TestSmallStringable, utils::LifetimeTracker::Session>(std::allocator<void>{}, & tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
Expand All @@ -205,7 +206,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_DirectAllocator_InPlaceInitializerLis
{
auto p = pro::allocate_proxy<spec::TestSmallStringable, utils::LifetimeTracker::Session>(std::allocator<void>{}, { 1, 2, 3 }, & tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kInitializerListConstruction);
Expand All @@ -223,11 +224,11 @@ TEST(ProxyCreationTests, TestAllocateProxy_DirectAllocator_Lifetime_Copy) {
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
auto p2 = p1;
ASSERT_TRUE(p1.has_value());
ASSERT_EQ(ToString(p1), "Session 1");
ASSERT_EQ(ToString(*p1), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p1).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p1).AllocatorAllocatesForItself);
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).AllocatorAllocatesForItself);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
Expand All @@ -247,7 +248,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_DirectAllocator_Lifetime_Move) {
auto p2 = std::move(p1);
ASSERT_FALSE(p1.has_value());
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 1");
ASSERT_EQ(ToString(*p2), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).AllocatorAllocatesForItself);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -265,7 +266,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_IndirectAllocator_FromValue) {
std::pmr::unsynchronized_pool_resource memory_pool;
auto p = pro::allocate_proxy<spec::TestSmallStringable>(std::pmr::polymorphic_allocator<>{&memory_pool}, session);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 2");
ASSERT_EQ(ToString(*p), "Session 2");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
Expand All @@ -282,7 +283,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_IndirectAllocator_InPlace) {
std::pmr::unsynchronized_pool_resource memory_pool;
auto p = pro::allocate_proxy<spec::TestSmallStringable, utils::LifetimeTracker::Session>(std::pmr::polymorphic_allocator<>{&memory_pool}, & tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
Expand All @@ -299,7 +300,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_IndirectAllocator_InPlaceInitializerL
std::pmr::unsynchronized_pool_resource memory_pool;
auto p = pro::allocate_proxy<spec::TestSmallStringable, utils::LifetimeTracker::Session>(std::pmr::polymorphic_allocator<>{&memory_pool}, { 1, 2, 3 }, & tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kInitializerListConstruction);
Expand All @@ -318,11 +319,11 @@ TEST(ProxyCreationTests, TestAllocateProxy_IndirectAllocator_Lifetime_Copy) {
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
auto p2 = p1;
ASSERT_TRUE(p1.has_value());
ASSERT_EQ(ToString(p1), "Session 1");
ASSERT_EQ(ToString(*p1), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p1).SboEnabled);
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p1).AllocatorAllocatesForItself);
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p2).AllocatorAllocatesForItself);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
Expand All @@ -343,7 +344,7 @@ TEST(ProxyCreationTests, TestAllocateProxy_IndirectAllocator_Lifetime_Move) {
auto p2 = std::move(p1);
ASSERT_FALSE(p1.has_value());
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 1");
ASSERT_EQ(ToString(*p2), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p2).AllocatorAllocatesForItself);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -360,7 +361,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithSBO_FromValue) {
{
auto p = pro::make_proxy<spec::TestLargeStringable>(session);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 2");
ASSERT_EQ(ToString(*p), "Session 2");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -375,7 +376,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithSBO_InPlace) {
{
auto p = pro::make_proxy<spec::TestLargeStringable, utils::LifetimeTracker::Session>(&tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -390,7 +391,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithSBO_InPlaceInitializerList) {
{
auto p = pro::make_proxy<spec::TestLargeStringable, utils::LifetimeTracker::Session>({ 1, 2, 3 }, &tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kInitializerListConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -407,10 +408,10 @@ TEST(ProxyCreationTests, TestMakeProxy_WithSBO_Lifetime_Copy) {
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
auto p2 = p1;
ASSERT_TRUE(p1.has_value());
ASSERT_EQ(ToString(p1), "Session 1");
ASSERT_EQ(ToString(*p1), "Session 1");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p1).SboEnabled);
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand All @@ -429,7 +430,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithSBO_Lifetime_Move) {
auto p2 = std::move(p1);
ASSERT_FALSE(p1.has_value());
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_TRUE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kMoveConstruction);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kDestruction);
Expand All @@ -447,7 +448,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithoutSBO_FromValue) {
{
auto p = pro::make_proxy<spec::TestSmallStringable>(session);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 2");
ASSERT_EQ(ToString(*p), "Session 2");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
Expand All @@ -463,7 +464,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithoutSBO_InPlace) {
{
auto p = pro::make_proxy<spec::TestSmallStringable, utils::LifetimeTracker::Session>(&tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
Expand All @@ -479,7 +480,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithoutSBO_InPlaceInitializerList) {
{
auto p = pro::make_proxy<spec::TestSmallStringable, utils::LifetimeTracker::Session>({ 1, 2, 3 }, &tracker);
ASSERT_TRUE(p.has_value());
ASSERT_EQ(ToString(p), "Session 1");
ASSERT_EQ(ToString(*p), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p).AllocatorAllocatesForItself);
expected_ops.emplace_back(1, utils::LifetimeOperationType::kInitializerListConstruction);
Expand All @@ -497,11 +498,11 @@ TEST(ProxyCreationTests, TestMakeProxy_WithoutSBO_Lifetime_Copy) {
expected_ops.emplace_back(1, utils::LifetimeOperationType::kValueConstruction);
auto p2 = p1;
ASSERT_TRUE(p1.has_value());
ASSERT_EQ(ToString(p1), "Session 1");
ASSERT_EQ(ToString(*p1), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p1).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p1).AllocatorAllocatesForItself);
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 2");
ASSERT_EQ(ToString(*p2), "Session 2");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).AllocatorAllocatesForItself);
expected_ops.emplace_back(2, utils::LifetimeOperationType::kCopyConstruction);
Expand All @@ -521,7 +522,7 @@ TEST(ProxyCreationTests, TestMakeProxy_WithoutSBO_Lifetime_Move) {
auto p2 = std::move(p1);
ASSERT_FALSE(p1.has_value());
ASSERT_TRUE(p2.has_value());
ASSERT_EQ(ToString(p2), "Session 1");
ASSERT_EQ(ToString(*p2), "Session 1");
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).SboEnabled);
ASSERT_FALSE(pro::proxy_reflect<SboObserver>(p2).AllocatorAllocatesForItself);
ASSERT_TRUE(tracker.GetOperations() == expected_ops);
Expand Down
Loading