我有这个非常好的包装,但我希望它接受任意数量的T,S,R,Q,......
template<typename U, typename T, typename S>
boost::variant<U, std::string> RunSafeFn2(const std::function<U(const T&,const S&)>& f, const std::string& errMsg, const T& a1, const S& a2)
{
try
{
return f(a1,a2);
}
catch (...)
{
return errMsg;
}
}
我尝试了下面的内容并且一直在谷歌上搜索,但是男人的错误信息是神秘的 - 我正在努力做甚至可能吗?
template<typename U, class ... Ts>
boost::variant<U, std::string> RunSafeFnN(const std::function<U(Ts)>& f, const std::string& errMsg, Ts ... ts)
{
try
{
return bind(f, ts...);
}
catch (...)
{
return errMsg;
}
}
答案 0 :(得分:6)
你可以做你想做的事,正如这个简单的程序所示:
The property 'add' cannot be found on this object. Verify that the property exists and can be set.
At line:1 char:1
+ $names.add = Foreach ($A in $grps.keys) {Get-DistributionGroupMember -Identity ' ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
问题是,一旦template <class ... Ts>
void foo(std::function<void(Ts...)> f, Ts && ... ts) {
f(std::forward<Ts>(ts)...);
}
int main()
{
std::function<void(int)> f = [] (int i) { std::cerr << "hello " << i; };
foo(f, 5);
return 0;
}
是模板,您也可以模拟仿函数本身。当您已经是模板时,键入擦除可调用的内容几乎没有什么好处。所以在实践中,这样做更有意义:
RunSafeFn2
仍允许上述用法,但也允许执行:
template <class F, class ... Ts>
void foo(F f, Ts && ... ts) {
f(std::forward<Ts>(ts)...);
}
由于您完全避免创建foo([] (int i) { std::cerr << "hello " << i; }, 5);
对象,因此效率也会更高。要处理返回类型,因为你只能使用C ++ 11,你可以这样做:
std::function
编辑:让我添加一个最后的想法:在C ++ 11及其中,callables很容易创建,更简单的替代方法实际上是采用可调用的 no 参数:
template <class F, class ... Ts>
auto foo(F f, Ts && ... ts) -> boost::variant<decltype(f(std::forward<Ts>(ts)...)), std::string> {
try {
return f(std::forward<Ts>(ts)...);
}
...
}
那是因为很容易捕捉到你需要的论据。例如,如果我以这种方式编写了我的原始示例,我可以通过执行以下操作来使用它:
template <class F>
auto foo(F f) -> boost::variant<decltype(f()), std::string> {
try {
return f();
}
...
}
这有利有弊,尤其是在处理移动类型时,但如果您想最大限度地减少维护负担并且您的用例很简单,那么这是一个合理的选择。