-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there any pattern that can combine overload and override? #208
Comments
@FlyinCow Thank you for asking. If I understand correctly, the semantics of your existing abstraction model relies on different types However, we do have heard some feedback suggesting we add RTTI support ( |
The feature requested here is, formally, a generic facade, or an overloaded facade. Ideally I want to dispatch call by function name, but I don't think this is doable, or at least it's not easily to be done with both efficiency and type safety. In my production code I have a traditional tagged union like RAII wrapper (a // This is a member function of the wrapper. `_attr` is the unique_ptr and `_type` is the enum.
// `if constexpr` here is to make these codes able to compile, and provide with a little safety.
template<class... Args>
void setValue(Args... args) {
switch (_type) {
case AttributeType::Int32:
if constexpr (std::is_invocable_v<decltype(&Int32Attribute::setValue), Int32Attribute *, Args...>) {
static_cast<Int32Attribute &>(*_attr).setValue(std::forward<Args>(args)...);
break;
} else {
throw something;
}
case AttributeType::UInt32:
if constexpr (std::is_invocable_v<decltype(&UInt32Attribute::setValue), UInt32Attribute *, Args...>) {
static_cast<UInt32Attribute &>(*_attr).setValue(std::forward<Args>(args)...);
} else {
throw something;
}
break;
...... The real reason I turn to struct D{
virtual void interface();
template<class T>
void generic_interface(); // this could not be virtual
};
struct B: D{
void interface() override; // It's nice, a `D*` pointer to a `new B` would call this
void interface(int); // no way to call it from `D*` without casting, and override key word cannot be used here
}; If I use CRTP then BTW the current user guides and documentation is not so easy to read. The README covers the most common situations, but it seems there's no advanced usage? It would be nice if the specifications has a navigation bar. And is there any plan to make a talk about this great work, like on CPPCON? |
@FlyinCow Thank you for the explanation and sorry for the delayed response. Although I can't tell if the design of abstraction can be optimized with limited context of your project, you can use #include <iostream>
#include "proxy.h"
struct CopyableObject : pro::facade_builder
::support_copy<pro::constraint_level::nontrivial> // Support copy
::support_rtti // Support proxy_cast, proxy_typeid
::build {}; // You can add whatever conventions you want
namespace details {
template <class T>
pro::proxy<CopyableObject> PolyGetValue(T&& self) {
return pro::make_proxy<CopyableObject>(self.getValue());
}
template <class T>
void PolySetValue(T&& self, pro::proxy<CopyableObject> val) {
using AttributeType = std::decay_t<decltype(std::declval<T>().getValue())>;
self.setValue(proxy_cast<AttributeType>(std::move(*val)));
}
} // namespace details
PRO_DEF_FREE_AS_MEM_DISPATCH(MemPolyGetValue, details::PolyGetValue, getValue);
PRO_DEF_FREE_AS_MEM_DISPATCH(MemPolySetValue, details::PolySetValue, setValue);
struct Attribute : pro::facade_builder
::add_convention<MemPolyGetValue, pro::proxy<CopyableObject>()>
::add_convention<MemPolySetValue, void(pro::proxy<CopyableObject>)>
::build {};
class IntAttribute {
public:
IntAttribute(int value) : data(value) {}
IntAttribute(const IntAttribute&) = default;
int getValue() { return data; }
void setValue(int value) { data = value; }
private:
int data;
};
int main() {
std::shared_ptr<IntAttribute> attribute = std::make_shared<IntAttribute>(123);
pro::proxy<Attribute> p = attribute; // p holds a copy of attribute
pro::proxy<CopyableObject> val = p->getValue();
std::cout << proxy_typeid(*val).name() << "\n";
proxy_cast<int&>(*val) = 456;
p->setValue(std::move(val));
std::cout << attribute->getValue() << "\n"; // Prints: "456"
} Note that the code above won't compile with version 3.1 or earlier because
Your ideas to improve documentation of the library is much appreciated! Please feel free to file a separate issue or a pull request.
Thank you for appreciating our work. We will consider your suggestion and maybe have some public talks next year. |
Say I have some c++ classes, each of them has a
get
and aset
. They are abstractions of "attributes":Naturally, different attribute types have different data types, therefore have different
get
andset
(mostlyT get()
andvoid set(T)
). I have to put them all together into a single container, so some polymorphism type is needed. But virtual functions can't help here because subclasses have different member function signatures.Furthermore, to support arbitrary data type I have something like:
Is there anything I can do with
proxy
to handle this situation? I can't figure out a way to dispatchget
andset
calls to subclasses. Currently I just dynamic convert a parent class into a subclass.The text was updated successfully, but these errors were encountered: