I'm trying to make a helper function that executes a lambda/std::function when called if the given weak_ptr is valid. Currently the following code works, but unfortunately, it requires me to define the template parameters. I'm looking for a way to do this with automatic template argument deduction.
template <typename DependentType, typename... ArgumentTypes>
auto make_dependent(std::weak_ptr<DependentType>& dependent, std::function < void(ArgumentTypes...)> functor) -> decltype(functor)
{
return [&dependent, functor] (ArgumentTypes... args)
{
if (!dependent.expired()) {
functor(args...);
}
};
};
Ideally, I would like to replace the std::function <void(ArgumentTypes...)>
with a generic template parameter FunctorType
, but then I'm not sure how I would extract arguments from FunctorType
. The above code works, the below code is theoretical:
template <typename DependentType, typename FunctorType>
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType functor) -> decltype(std::function<return_value(functor)(argument_list(functor))>)
{
return[&dependent, functor](argument_list(functor) args)
{
if (!dependent.expired()) {
functor(args...);
}
}
}
Is there any way to do something like this?
The easiest way to solve your problem with extracting arguments from your parameter is to not extract the arguments from your parameter.
template<typename F, typename C>
struct conditional_forwarder {
F func;
C cond;
template<typename Fin, typename Cin>
conditional_forwarder( Fin&& f, Cin&& c ):
func(std::forward<Fin>(f)), cond(std::forward<Cin>(c)) {}
template<typename... Args>
void operator()( Args&&... args ) const {
if (cond())
func( std::forward<Args>(args)... );
}
};
template<typename F, typename C>
conditional_forwarder< typename std::decay<F>::type, typename std::decay<C>::type >
make_conditional_forwarder( F&& f, C&& c ) {
return {std::forward<F>(f), std::forward<C>(c)};
}
// todo: make_dependent_test
template <typename DependentType, typename FunctorType>
auto make_dependent_ideal(std::weak_ptr<DependentType>& dependent, FunctorType functor)
-> decltype(make_conditional_forwarder( make_dependent_test(dependent), functor) )
{
return make_conditional_forwarder( make_dependent_test(dependent), functor);
}
much of this will be easier in C++14.
As an aside, there seems to be a fundamental design flaw: the conditional forwarder should probably aquire a .lock()
on the weak_ptr
, and then execute functor
within that lock, so that the precondition (that the resource is held) holds for the entire call of functor
.
I'm also unsure why you are holding a reference to a weak_ptr
, when the remote state of a weak_ptr
can be copied.
In C++14, you can return something like:
return [=](auto&&... args) mutable {
}
I believe, and the decltype
stuff also goes away mostly as functions can deduce their return type more easily.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With