问题的根本原因似乎是 std::bind 执行其参数的内部复制,特别是 t .
您可能希望以这种方式解决它:
template
explicit X(T t)
{
std::bind(&X::invoke, this, std::placeholders::_1)(t);
// ^^^^^^^^^^^^^^^^^^^^^ ^
}
这也可以,但是你不会允许 bind 的结果超过参数 t (否则,你会将悬空引用传递给 invoke() ):
template
explicit X(T t)
{
std::bind(&X::invoke, this, cref(t))();
// ^^^^^^^
}
UPDATE:
上述解决方案是有助于实现您在示例中显示的内容的解决方法 . 但是,从评论中可以看出,您的用例可能大不相同(例如,传递 bind 的结果以供以后评估) .
正如Maxim Yegorushkin在他的回答中正确指出的那样,概念上正确的解决方案在于使用诸如Boost的 protect 之类的构造 .
如果您不想使用Boost,使用C 11的可变参数模板定义您自己的 protect() 函数非常容易:
// Imitates boost::protect, but with variadic templates and perfect forwarding
namespace detail
{
template
struct protect
{
private:
F _f;
public:
explicit protect(F f): _f(f)
{
}
template
auto operator () (Ts&&... args) ->
decltype(_f(std::forward(args)...))
{
return _f(std::forward(args)...);
}
};
}
template
detail::protect protect(F&& f)
{
return detail::protect(std::forward(f));
}
最终,这是你在课堂上使用它的方式,正如Maxim建议的那样:
class X
{
public:
template
explicit X(T t)
{
auto pt = protect(t);
std::bind(&X::invoke, this, pt)();
}
private:
template
void invoke(T t)
{
t();
}
};