Both of the following code compiles and performs as expected, are they different?
template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args)
{
std::cout << "timing" << std::endl;
auto val = std::forward<T>(func)(std::forward<U...>(args...));
std::cout << "timing over" << std::endl;
return val;
}
template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args)
{
std::cout << "timing" << std::endl;
auto val = std::forward<T>(func)(std::forward<U>(args)...);
std::cout << "timing over" << std::endl;
return val;
}
Looking at SO How would one call std::forward on all arguments in a variadic function?, second seems to be recommended, but doesn't the first do the same thing?
They are not the same. They are the same in the case that the arity of args
is 1 or 0. otherwise it will fail to compile, consider..
#include <iostream>
using namespace std;
template<typename T, typename ...U>
auto time_function_1(T&& func, U&& ...args)
{
std::cout<<"timing"<<std::endl;
auto val = std::forward<T>(func)(std::forward<U...>(args...));
std::cout<<"timing over"<<std::endl;
return val;
}
template<typename T, typename ...U>
auto time_function_2(T&& func, U&& ...args)
{
std::cout<<"timing"<<std::endl;
auto val = std::forward<T>(func)(std::forward<U>(args)...);
std::cout<<"timing over"<<std::endl;
return val;
}
int f (int){return 0;}
int y (int,int){return 0;}
int main() {
time_function_1(f,1);
time_function_2(f,1);
time_function_1(y,1,2); // fail
time_function_2(y,1,2);
return 0;
}
for the failing case std::forward<U...>(args...)
expands to forward<int, int>(int&, int&)
and will fail to compile.
std::forward<U>(args)...
expands to std::forward<int>(int&),std::forward<int>(int&)