Reputation: 153
I have a class that creates a wrapper functor to deal with a weak_ptr to an object. When the functor executes, it will test the weak_ptr before invoking the object functor.
Additionally, the wrapper functor can return a default value if the object no longer exists.
This is an excerpt of a class that compiles under GCC 4.4.7...
class Bind
{
public:
// non-void weak-functor
template <typename R>
struct Wrapper<R, typename std::enable_if<!std::is_void<R>::value>::type>
{
using result_type = R;
template <typename O>
R operator()(const std::weak_ptr<O> && obj,
std::function<R()> && func, R && ret)
{
if (auto ptr = obj.lock())
{
return func();
}
return std::forward<R>(ret);
}
};
// weak from shared - non-void return
template <typename R, typename F, typename O, typename... A>
static std::function<R()> Weak(R && ret,
F func,
const std::shared_ptr<O> && obj,
A&&... args)
{
return std::bind(Wrapper<R>(),
std::weak_ptr<O>(obj),
std::function<R()>(std::bind(func, obj.get(),
std::forward<A>(args)...)),
ret);
}
// ...
};
The class can be used like this...
auto x = std::make_shared<X>();
auto f = Bind::Weak(false, &X::foo, x, 1, 2, 3);
f(); // returns x::foo(1, 2, 3)
x.reset()
f(); // returns false
Unfortunately, after upgrading the compiler to GCC 4.8.3 it no longer compiles. The error starts like this...
error: could not convert 'std::bind(_Func&&, _BoundArgs&& ...)
...with the usual mountain of template crud. The jist is that it can no longer convert the result of std::bind() inside Bind::Weak() into the return type of Bind::Weak().
I've fiddled with this for a few hours now and haven't been able to resolve the issue.
Upvotes: 1
Views: 1315
Reputation: 98388
The problem is that you cannot do perfect forwarding using a std::function
because the std::function
is required to be copyable, so the bound values have to be copiable, too.
Changing the operator()
prototype to:
template<typename O>
R operator()(const std::weak_ptr<O>& obj, const std::function<R()>& func, const R& ret)
{
//...
}
Should be more or less enough to make this work (it is difficult to be sure because your posted code is not complete).
But now that your forwarding into the binding is destroyed, all those std::forward
and &&
do not make much sense, IMO.
Upvotes: 1