Skip to content
This repository was archived by the owner on Jan 29, 2026. It is now read-only.

Commit 7f11ac5

Browse files
authored
Fix proxy_view with facade-aware overloads (#347)
1 parent 0ce3e89 commit 7f11ac5

File tree

2 files changed

+67
-38
lines changed

2 files changed

+67
-38
lines changed

include/proxy/v4/proxy.h

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,52 +1931,34 @@ using observer_upward_conversion_conv = recursive_reduction_t<
19311931
reduction_traits<observer_upward_conversion_conv_reduction>::template type,
19321932
conv_impl<true, upward_conversion_dispatch>, Os...>;
19331933

1934-
template <class D, class F, class... Os>
1935-
using observer_indirect_conv =
1936-
conv_impl<false, D, substituted_overload_t<Os, F>...>;
1934+
template <class D, class... Os>
1935+
using observer_indirect_conv = conv_impl<false, D, Os...>;
19371936

1938-
template <class C, class F>
1939-
struct observer_conv_traits : inapplicable_traits {};
1940-
template <class C, class F>
1941-
requires(C::is_direct && std::is_same_v<typename C::dispatch_type,
1942-
upward_conversion_dispatch>)
1943-
struct observer_conv_traits<C, F>
1944-
: applicable_traits,
1945-
std::type_identity<instantiated_t<observer_upward_conversion_conv,
1937+
template <class C>
1938+
struct observer_conv_traits : std::type_identity<void> {};
1939+
template <class C>
1940+
requires(
1941+
C::is_direct &&
1942+
std::is_same_v<typename C::dispatch_type, upward_conversion_dispatch>)
1943+
struct observer_conv_traits<C>
1944+
: std::type_identity<instantiated_t<observer_upward_conversion_conv,
19461945
typename C::overload_types>> {};
1947-
template <class C, class F>
1946+
template <class C>
19481947
requires(!C::is_direct)
1949-
struct observer_conv_traits<C, F>
1950-
: applicable_traits,
1951-
std::type_identity<
1952-
instantiated_t<observer_indirect_conv, typename C::overload_types,
1953-
typename C::dispatch_type, F>> {};
1954-
1955-
template <class F, class O, class I>
1956-
struct observer_conv_reduction : std::type_identity<O> {};
1957-
template <class F, class... Cs, class I>
1958-
requires(observer_conv_traits<I, F>::applicable)
1959-
struct observer_conv_reduction<F, std::tuple<Cs...>, I>
1948+
struct observer_conv_traits<C>
19601949
: std::type_identity<
1961-
std::tuple<Cs..., typename observer_conv_traits<I, F>::type>> {};
1962-
template <class F, class... Cs>
1950+
instantiated_t<observer_indirect_conv, typename C::overload_types,
1951+
typename C::dispatch_type>> {};
1952+
template <class... Cs>
19631953
struct observer_facade_conv_impl {
1964-
using convention_types = recursive_reduction_t<
1965-
reduction_traits<observer_conv_reduction, F>::template type, std::tuple<>,
1966-
Cs...>;
1954+
using convention_types =
1955+
composite_t<std::tuple<>, typename observer_conv_traits<Cs>::type...>;
19671956
};
19681957

1969-
template <class O, class I>
1970-
struct observer_refl_reduction : std::type_identity<O> {};
1971-
template <class... Rs, class R>
1972-
requires(!R::is_direct)
1973-
struct observer_refl_reduction<std::tuple<Rs...>, R>
1974-
: std::type_identity<std::tuple<Rs..., R>> {};
19751958
template <class... Rs>
19761959
struct observer_facade_refl_impl {
1977-
using reflection_types = recursive_reduction_t<
1978-
reduction_traits<observer_refl_reduction>::template type, std::tuple<>,
1979-
Rs...>;
1960+
using reflection_types =
1961+
composite_t<std::tuple<>, std::conditional_t<Rs::is_direct, void, Rs>...>;
19801962
};
19811963

19821964
template <class P>
@@ -2040,7 +2022,7 @@ struct weak_facade_impl {
20402022
template <facade F>
20412023
struct observer_facade
20422024
: details::instantiated_t<details::observer_facade_conv_impl,
2043-
typename F::convention_types, F>,
2025+
typename F::convention_types>,
20442026
details::instantiated_t<details::observer_facade_refl_impl,
20452027
typename F::reflection_types> {
20462028
static constexpr std::size_t max_size = sizeof(void*);

tests/proxy_view_tests.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,38 @@ static_assert(
3838
SupportsToString<decltype(*std::declval<pro::proxy_view<TestFacade>>())>);
3939
static_assert(sizeof(pro::proxy_view<TestFacade>) == 3 * sizeof(void*));
4040

41+
template <class F>
42+
using AreEqualOverload = bool(const pro::proxy_indirect_accessor<F>& rhs,
43+
double eps) const;
44+
45+
template <class T, pro::facade F>
46+
bool AreEqualImpl(const T& lhs, const pro::proxy_indirect_accessor<F>& rhs,
47+
double eps) {
48+
return lhs.AreEqual(proxy_cast<const T&>(rhs), eps);
49+
}
50+
51+
PRO_DEF_FREE_AS_MEM_DISPATCH(MemAreEqual, AreEqualImpl, AreEqual);
52+
53+
struct EqualableQuantity
54+
: pro::facade_builder //
55+
::add_skill<pro::skills::rtti> // for proxy_cast
56+
::add_convention<MemAreEqual,
57+
pro::facade_aware_overload_t<AreEqualOverload>> //
58+
::build {};
59+
60+
class Point_2 {
61+
public:
62+
Point_2(double x, double y) : x_(x), y_(y) {}
63+
Point_2(const Point_2&) = default;
64+
Point_2& operator=(const Point_2&) = default;
65+
bool AreEqual(const Point_2& rhs, double eps) const {
66+
return std::abs(x_ - rhs.x_) < eps && std::abs(y_ - rhs.y_) < eps;
67+
}
68+
69+
private:
70+
double x_, y_;
71+
};
72+
4173
} // namespace proxy_view_tests_details
4274

4375
namespace details = proxy_view_tests_details;
@@ -132,3 +164,18 @@ TEST(ProxyViewTests, TestUpwardConversion_FromValue) {
132164
ASSERT_EQ(ToString(*p2), "123");
133165
ASSERT_EQ(ToString(*p3), "123");
134166
}
167+
168+
TEST(ProxyViewTests, TestFacadeAware) {
169+
details::Point_2 v1{1, 1};
170+
details::Point_2 v2{1, 0};
171+
details::Point_2 v3{1.0000001, 1.0000001};
172+
pro::proxy_view<details::EqualableQuantity> p1 =
173+
pro::make_proxy_view<details::EqualableQuantity>(v1);
174+
pro::proxy_view<details::EqualableQuantity> p2 =
175+
pro::make_proxy_view<details::EqualableQuantity>(v2);
176+
pro::proxy_view<details::EqualableQuantity> p3 =
177+
pro::make_proxy_view<details::EqualableQuantity>(v3);
178+
ASSERT_TRUE(p1->AreEqual(*p1, 1e-6));
179+
ASSERT_FALSE(p1->AreEqual(*p2, 1e-6));
180+
ASSERT_TRUE(p1->AreEqual(*p3, 1e-6));
181+
}

0 commit comments

Comments
 (0)