无法为包装器功能添加完美的转发

Can't add perfect forwarding to wrapper function

本文关键字:添加 完美 转发 功能 包装      更新时间:2023-10-16

在回答这个问题时,我写了这个工作代码,包装在模板参数中传递的函数:

template<typename Fn, Fn fn, typename... Args>
auto wrapper(Args... args)->decltype(fn(args...)){
    return fn(args...);
}
#define WRAPPER(FUNC) wrapper<decltype(&FUNC), &FUNC>

示例用法(我使用此代码进行测试(:

int min(int a, int b){
    return (a<b)?a:b;
}
#include<iostream>
using std::cout;
int main(){
    cout<<WRAPPER(min)(10, 20)<<'n';
}

有两个人告诉我使用完美的转发。当我问如何做到这一点时,其中一个人将我重定向到这里。我读了问题,仔细阅读了最佳答案,wrapper改为:

#include<utility>
template<typename Fn, Fn fn, typename... Args>
auto wrapper(Args&&... args)->decltype(fn(std::forward<Args...>(args...))){
    return fn(std::forward<Args...>(args...));
}

它可以编译,除非我尝试使用上面的示例代码检查它。如何修复代码?

http://rextester.com/YUIYI99787

你在 return 语句上的错误位置有点。你想要:

return fn(std::forward<Args>(args)...);

这将扩展到:

return fn(std::forward<T1>(t1), std::forward<T1>(t2), ...);

你写的内容会扩展到:

return fn(std::forward<T1,T2,...>(t1, t2, t3)); 

诀窍是,每次你看到"......"时,想想"它会复制它背后的东西"。这可能会变得棘手,因为有各种各样的方法可以构建"它背后的东西",包括能够做一个交叉产品等。

#include<utility>
template<typename Fn, Fn fn, typename... Args>
auto wrapper(Args&&... args)->decltype(fn(std::forward<Args>(args)...)){
//                             vvvvvvvvvv---- Oopsie ! ----^^^^^^^^^^
    return fn(std::forward<Args>(args)...);
}

在每行上,单个省略号将并行展开Argsargs。你最终会得到:

std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), ...

。而不是不正确的:

std::forward<Arg1, Arg2, ...>(arg1, arg2, ....)

您可能还对 std::result_of 感兴趣,以稍微修剪一下衰减:

#include<utility>
template<typename Fn, Fn fn, typename... Args>
auto wrapper(Args&&... args) -> std::result_of<Fn(Args...)>::type {
    return fn(std::forward<Args>(args)...);
}