我正在开发一种用于创建“安全”回调的机制,该回调在其父对象被销毁后调用时不会引起未定义的行为。该类应具有足够的通用性,以便能够包装任何回调,并根据它们所绑定的对象的状态,简单地执行是否执行void(...)回调,以及返回值返回boost的回调::可选,如果执行则返回值;如果未执行则返回boost :: none。实现几乎完成,但是有两件事让我担心我不完全了解我的代码...
如果第19行未注释并且第18行被注释掉,则模板将无法编译-这仅仅是可以解决的语法问题,还是我尝试不正确地使用result_of机制(是否对std :: forward进行了更改语义还是多余?)
如果未注释第88行并注释掉了89行,则由于对fun的函数调用的含糊不清,导致编译失败,我对此不太了解-在我看来fun(int &&)完全匹配,那么为什么编译器会抱怨fun(int)版本的模棱两可?
如果还有其他细微(或严重)错误,请也发表评论。
谢谢。
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <memory>
#include <boost/optional.hpp>
template<class Func>
class SafeCallback
{
public:
SafeCallback(std::shared_ptr<bool> guard, const Func& callback)
: guard_(guard)
, callback_(callback)
{}
template<class... Args>
// auto operator()(Args&&... args) -> typename std::enable_if<std::is_void<typename std::result_of<Func(std::forward<Args>(args)...)>::type>::value, // won't compile with: 19:91: error: invalid use of template-name 'std::result_of' without an argument list
auto operator()(Args&&... args) -> typename std::enable_if<std::is_void<typename std::result_of<Func(Args...)>::type>::value,
void>::type
{
std::cout << "trying void callback" << std::endl;
if(guard_.lock())
{
std::cout << "callback is still alive :)" << std::endl;
callback_(std::forward<Args>(args)...);
return;
}
std::cout << "uh-oh, callback is dead!" << std::endl;
}
template<class... Args>
auto operator()(Args&&... args) -> typename std::enable_if<!std::is_void<typename std::result_of<Func(Args...)>::type>::value,
boost::optional<typename std::result_of<Func(Args...)>::type>>::type
{
std::cout << "trying non-void callback" << std::endl;
if(guard_.lock())
{
std::cout << "callback is still alive :)" << std::endl;
return callback_(std::forward<Args>(args)...);
}
std::cout << "uh-oh, callback is dead!" << std::endl;
return boost::none;
}
bool isAlive()
{
return guard_.lock();
}
private:
std::weak_ptr<bool> guard_;
Func callback_;
};
class SafeCallbackProvider
{
public:
SafeCallbackProvider()
: guard_(new bool(true))
{}
virtual ~SafeCallbackProvider() = default;
template<class Func>
SafeCallback<Func> makeSafeCallback(const Func& callback)
{
return SafeCallback<Func>(guard_, callback);
}
private:
std::shared_ptr<bool> guard_;
};
struct A : SafeCallbackProvider
{
void fun()
{
std::cout << "---this is fun---" << std::endl;
}
int fun(int&& i)
{
std::cout << "&& this is && " << i << " && fun &&" << std::endl;
return i;
}
// int fun(int i) // fails to compile with: 123:48: error: call of overloaded 'fun(int)' is ambiguous
int fun(int& i)
{
std::cout << "---this is ---" << i << "--- fun---" << std::endl;
return i;
}
};
int main()
{
A* a= new A;
auto cb = a->makeSafeCallback(
[&]()
{
a->fun();
});
cb();
delete a;
cb();
std::cout << "\n----------\n\n";
A* a2= new A;
auto cb2 = a2->makeSafeCallback(
[&](int i)
{
return a2->fun(i);
});
cb2(5);
delete a2;
cb2(5);
std::cout << "\n----------\n\n";
A* a3= new A;
auto cb3 = a3->makeSafeCallback(
[&](int&& i)
{
return a3->fun(std::forward<int>(i));
});
cb3(5);
delete a3;
cb3(5);
return 0;
}
答案 0 :(得分:3)
注意:这只能回答第一个问题,因为我显然注意力集中。更多即将推出。
std::result_of
本质上基于看起来像函数 call 的函数 type 执行一些魔术操作。在有效的行中:
typename std::result_of<Func(Args...)>::type
这是预期的用途,它模拟类型为Func
的值的Args...
实例的调用。另一方面:
typename std::result_of<Func(std::forward<Args>(args)...)>::type
这会将Args
和args
扩展为一组值,然后在函子样式强制转换为{ {1}}。整个过程都是表达式,而不是,
期望的类型。
您似乎正要使用Func
的一半,它看起来像:
std::result_of
...,或者,如果您不愿意将其移动到decltype
的声明下:
decltype(std::declval<Func&>()(std::forward<Args>(args)...))
答案 1 :(得分:0)
超载规则就是这样。
功能的签名应该不同。
在两种情况下,编译器都找到相同的签名,请尝试更改签名并查看结果。