Can't add perfect forwarding to wrapper function

怎甘沉沦 提交于 2019-12-06 08:48:34

问题


While answering this question I wrote this working code, wrapping function passed in template arguments:

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

Example usage (I use this code for testing):

int min(int a, int b){
    return (a<b)?a:b;
}

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

Two people told me to use perfect forwarding. When I asked how to do this, one of them redirected me here. I read question, carefully read best answer, and changed wrapper to:

#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...));
}

It compiles, unless I attempt to check it out using example code above. How can I fix the code?

http://rextester.com/YUIYI99787


回答1:


You have the dots in the wrong place on the return statement. You want:

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

This will expand to:

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

What you wrote would have expanded to:

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

The trick is that everytime you see "...", think "it will replicate the thing behind it". This can get tricky because there are all sorts of ways to construct the "thing behind it", including being able to do a cross-product and the like.




回答2:


#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)...);
}

On each line, the single ellipsis will expand both Args and args in parallel. You will end up with :

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

... rather than the incorrect :

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

You might also be interested in std::result_of to trim that declatation a bit :

#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)...);
}


来源:https://stackoverflow.com/questions/25407804/cant-add-perfect-forwarding-to-wrapper-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!