I am just thinking about a way to check an object to be valid in a automated way. I have a couple of hardware related objects (like class A), which can be deleted by external (physical) events.
To detect this I have used shared/weak pointer. But now I am struggling with the checking of the weak pointer. Since this is done in the same way for each member function for many objects, I am currently searching for a way to do this with less redundant code. In addition I am writing a library and do not want the user to handle this (simply return the weak pointer to the user to handle it by himself is therefor no option)
My best guess is shown below. My problem is, I could not find a way to generate the member functions (func1, and many more ...) automatically within the template. Doing it by myself would result in lot of redundant code for every member function to be validated (and there are a lot)
Each member function of A (and many more other objects) shall be wrapped by a function doing the validation shown below. This is same for all member functions and done for many classes which can be used as type for the Validator. Does anyone has an idea how to solve this? Maybe there are other (better) ways to solve this. Many thanks for your help.
Some constraints: Only C 11 possible, No exceptions
class A {
public:
void func1() {}
//many more functions
};
template<typename T>
class Validator
{
//has to be done for all functions of A
void func1()
{
if (!wptr.expired())
{
wptr.lock()->func1();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
CodePudding user response:
I would protect the full user function call:
class A {
public:
void func1() {}
//many more functions
};
template <typename T>
class Validator
{
public:
#if 1 // template way, but no-expressive signature
template <typename F>
void do_job(F f)
#else // type-erasure way, expressive, but with some overhead
void do_job(std::function<void (T&)> f)
#endif
{
auto t = wptr.lock();
if (t) {
f(*t);
} else {
errorHandling();
}
}
private:
void errorHandling();
private:
std::weak_ptr<T> wptr;
};
So user might chain call:
Validator<A> val;
val.do_job([](A& a)
{
a.func1();
a.func2();
});
CodePudding user response:
If the caller can live with clunky syntax you can use member function pointers:
#include <memory>
#include <iostream>
class A {
public:
void func1() {
std::cout << "hello func1\n";
}
};
template<typename T>
class Validator
{
public:
Validator(std::shared_ptr<T> p) : wptr(p) {}
template <typename MemFun>
void call(MemFun mf) {
if (!wptr.expired())
{
(wptr.lock().get()->*mf)();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
int main() {
auto x = std::make_shared<A>();
Validator<A> v{x};
v.call(&A::func1);
}