The root cause of the problem is the internal copying of its arguments by std::bind , with a special reference to t .
You might want a workaround:
template <typename T> explicit X(T t) { std::bind(&X::invoke<T>, this, std::placeholders::_1)(t);
This will also work, but you will not be able to make the bind result survive the t argument (otherwise you will pass a dangling link to invoke<T>() ):
template <typename T> explicit X(T t) { std::bind(&X::invoke<T>, this, cref(t))();
UPDATE:
The above solutions are workarounds that help achieve what you show in your example. However, it follows from the comments that your use case may be completely different (for example, passing a bind result for further evaluation).
As Maxim Egorushkin correctly pointed out in his answer, the conceptually correct solution is to use a design such as Boost protect .
If you don't want to use Boost, it's pretty simple to define your own protect() function using C ++ 11 variadic templates:
// Imitates boost::protect, but with variadic templates and perfect forwarding namespace detail { template<typename F> struct protect { private: F _f; public: explicit protect(F f): _f(f) { } template<typename... Ts> auto operator () (Ts&&... args) -> decltype(_f(std::forward<Ts>(args)...)) { return _f(std::forward<Ts>(args)...); } }; } template<typename F> detail::protect<F> protect(F&& f) { return detail::protect<F>(std::forward<F>(f)); }
In the end, so you can use it in your class, as Maxim suggested:
class X { public: template <typename T> explicit X(T t) { auto pt = protect(t); std::bind(&X::invoke<decltype(pt)>, this, pt)(); } private: template <typename T> void invoke(T t) { t(); } };
Andy prowl
source share