I asked previously about the following class, which is a wrapper around a member function. I now want to add "plugin" functionality to it via a proxy class. My wrapper class's operator*
returns a proxy object on which I can then assign and retrieve as shown below:
#include <cstdio>
#include <type_traits>
#include <utility>
using namespace std;
class testclass {
public:
double get() { return d_; }
void set(double d) { d_ = d; }
double d_ = 0.0;
};
template <typename PropertyType>
struct DEFAULT_WRAPPER_PROXY {
DEFAULT_WRAPPER_PROXY(PropertyType* p) : property_(p) {}
operator typename PropertyType::GetterReturnType() {
return property_->Get();
}
DEFAULT_WRAPPER_PROXY& operator=(typename PropertyType::GetterReturnType val) {
property_->Set(val);
return *this;
}
PropertyType* property_;
};
template <typename PropertyType>
struct LOGGING_WRAPPER_PROXY {
LOGGING_WRAPPER_PROXY(PropertyType* p) : property_(p) {}
operator typename PropertyType::GetterReturnType() {
// Log some interesting stuff
return property_->Get();
}
LOGGING_WRAPPER_PROXY& operator=(typename PropertyType::GetterReturnType val) {
// Log some interesting stuff
property_->Set(val);
return *this;
}
PropertyType* property_;
};
template<typename Retriever, typename Updater, typename OwningClass, template<typename PropertyType> class WRAPPER_PROXY = DEFAULT_WRAPPER_PROXY>
struct Wrapper {
Wrapper(Retriever retriever, Updater updater, OwningClass* owner) : retriever_(retriever), updater_(updater), containingClass_(owner) {}
using GetterReturnType = std::invoke_result_t<Retriever, OwningClass>;
GetterReturnType Get() { return (containingClass_->*retriever_)(); }
template<typename...Args>
using SetterReturnType = std::invoke_result_t<Updater, OwningClass, Args...>;
template<typename...Args>
SetterReturnType<Args...> Set(Args&&... args) { return (containingClass_->*updater_)((forward<Args>(args))...); }
WRAPPER_PROXY<Wrapper<Retriever, Updater, OwningClass>> operator*() {
return WRAPPER_PROXY(this);
}
Retriever retriever_;
Updater updater_;
OwningClass* containingClass_;
};
int main() {
testclass tc;
{
// Can use template arg deduction in construction
Wrapper pp(&testclass::get, &testclass::set, &tc);
// use default proxy
double y = *pp;
*pp = 102;
}
{
// Try and use the logging proxy
// Does not work: LWT is not a template
//using LWT = LOGGING_WRAPPER_PROXY<Wrapper<decltype(testclass::get), decltype(testclass::set), testclass>>;
//Wrapper<decltype(testclass::get), decltype(testclass::set), testclass, LWT> pp2(&testclass::get, &testclass::set, &tc);
// Does not work;see errors below
Wrapper<decltype(testclass::get), decltype(testclass::set), testclass, LOGGING_WRAPPER_PROXY> pp2(&testclass::get, &testclass::set, &tc);
}
}
The errors I get are as follows:
'std::invoke_result_t' : Failed to specialize alias template
'type': is not a member of any direct or indirect base class of 'std::_Invoke_traits_nonzero<void,Retriever,OwningClass>'
Can anyone suggest a nice way I can achieve this plugin functionality please?