How to create a proxy object that is composed of another proxy object of the same type?
revtronix opened this issue · comments
Is there a way to create a proxy object that is composed of another proxy object of the same type? This could be used to create a UI hierarchy for example.
The following example doesn't compile, but can compile once the drawable member variable of Rectangle is removed.
// Abstraction
struct Draw : pro::dispatch<void()> {
template <class T>
void operator()(const T& self) { self.draw(); }
};
struct DrawableFacade : pro::facade<Draw> {};
// Implementation
class Rectangle {
public:
void draw() const {
drawable.invoke();
};
pro::proxy<DrawableFacade> drawable;
};
// Client - Producer
pro::proxy<DrawableFacade> CreateRectangleAsDrawable(int width, int height) {
Rectangle rect;
return pro::make_proxy<DrawableFacade>(rect);
}
Here is the error output when compiled in VS2022 17.8.1:
.\proxy\proxy.h(273): error C2131: expression did not evaluate to a constant
...\proxy\proxy.h(273): note: failure was caused by a read of an uninitialized symbol
...\proxy\proxy.h(273): note: see usage of 'pro::proxiable<pro::details::deep_ptr<Rectangle>,DrawableFacade>'
...\proxy\proxy.h(273): note: the template instantiation context (the oldest one first) is
...\layout.cpp(61): note: see reference to function template instantiation 'pro::proxy<DrawableFacade> pro::make_proxy<DrawableFacade,Rectangle&>(T)' being compiled
with
[
T=Rectangle &
]
...\proxy\proxy.h(521): note: see reference to function template instantiation 'pro::proxy<DrawableFacade> pro::details::make_proxy_impl<DrawableFacade,Rectangle,Rectangle&>(Rectangle &)' being compiled
...\proxy\proxy.h(343): note: see reference to variable template 'const bool pro::proxy<DrawableFacade>::HasPolyConstructor<pro::details::deep_ptr<Rectangle>,Rectangle &>' being compiled
...\proxy\proxy.h(273): note: see reference to variable template 'bool proxiable<pro::details::deep_ptr<Rectangle>,DrawableFacade>' being compiled
...\proxy\proxy.h(260): note: see reference to variable template 'const bool pro::details::facade_traits_impl<DrawableFacade,std::tuple<Draw> >::applicable_pointer<pro::details::deep_ptr<Rectangle> >' being compiled
...\proxy\proxy.h(238): note: see reference to function template instantiation 'bool pro::details::has_copyability<pro::details::deep_ptr<Rectangle>>(pro::constraint_level)' being compiled
...\proxy\proxy.h(50): note: see reference to variable template 'const bool is_trivially_copy_constructible_v<pro::details::deep_ptr<Rectangle> >' being compiled
...\proxy\proxy.h(491): note: see reference to variable template 'const bool is_constructible_v<Rectangle,pro::details::deep_ptr<Rectangle> const &>' being compiled
...\proxy\proxy.h(338): note: see reference to variable template 'const bool pro::proxy<DrawableFacade>::HasPolyConstructor<pro::details::deep_ptr<Rectangle>,pro::details::deep_ptr<Rectangle> const &>' being compiled
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtr1common(69): error C2131: expression did not evaluate to a constant
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtr1common(69): note: failure was caused by a read of an uninitialized symbol
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtr1common(69): note: see usage of 'pro::proxiable<pro::details::deep_ptr<Rectangle>,DrawableFacade>'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\xtr1common(69): note: the template instantiation context (the oldest one first) is
...\proxy\proxy.h(272): note: see reference to alias template instantiation 'std::conditional_t<pro::proxiable<pro::details::deep_ptr<Rectangle>,DrawableFacade>,std::is_constructible<pro::details::deep_ptr<Rectangle>,const pro::details::deep_ptr<Rectangle> &>,std::integral_constant<bool,false>>' being compiled
...\proxy\proxy.h(506): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'pro::proxy<DrawableFacade>'
...\proxy\proxy.h(506): note: 'pro::proxy<DrawableFacade>::proxy': function does not take 2 arguments
...\proxy\proxy.h(346): note: could be 'pro::proxy<DrawableFacade>::proxy(std::in_place_type_t<_Ty>,std::initializer_list<_Elem>,Args &&...) noexcept(<expr>)'
...\proxy\proxy.h(341): note: or 'pro::proxy<DrawableFacade>::proxy(std::in_place_type_t<_Ty>,Args &&...) noexcept(<expr>)'
...\proxy\proxy.h(337): note: or 'pro::proxy<DrawableFacade>::proxy(P &&) noexcept(<expr>)'
...\proxy\proxy.h(506): note: while trying to match the argument list '(const std::in_place_type_t<pro::details::deep_ptr<Rectangle>>, Rectangle)'
By default, pro::facade<>
specifies a move-only proxy, making Rectangle
also move-only. This code won't compile because in pro::make_proxy<DrawableFacade>(rect)
, rect
is passed by lvalue reference, pro::make_proxy()
will try to copy the value, but Rectangle
is not copiable.
There are two ways to fix the code:
- Change
pro::make_proxy<DrawableFacade>(rect)
topro::make_proxy<DrawableFacade>(std::move(rect))
, or - Add
static constexpr auto minimum_copyability = pro::constraint_level::nontrivial;
into the body ofstruct DrawableFacade
, to makepro::proxy<DrawableFacade>
copiable.
Thank you for your quick reply. I was able to compile the example after adding your suggestion and also a default constructor to the Rectangle class.