问题
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