今天我正在学习完美转发,我创建了这个代码示例
#include <utility>
#include <functional>
template<typename Function, typename... Args>
auto toStdFun(Function&& fun, Args&&...args)
{
using retType = decltype(fun(std::forward<Args>(args)...));
return std::function<retType(decltype(std::forward<Args>(args))...)>(fun);
}
int main()
{
toStdFun([] () {});
}
然后,有人告诉我使用decltype(std::forward<Args>(args))...
可以简单地用Args&&...
代表:
#include <utility>
#include <functional>
template<typename Function, typename... Args>
auto toStdFun(Function&& fun, Args&&...args)
{
using retType = decltype(fun(std::forward<Args>(args)...));
return std::function<retType(Args&&...)>(fun);
}
int main()
{
toStdFun([] () {});
}
两个样本之间有什么区别?
答案 0 :(得分:6)
std::forward<T>
只会将&&
添加到T
类型,并在用于转发参数时应用参考折叠规则。 Args&&...
所以恕我直言,decltype(std::forward<Args>(args))...
和Args&&...
是相同的。
答案 1 :(得分:0)
我建议你使用另一种语法。 你的代码在你的toStdFun的lambda之后需要以逗号分隔的形式作为VALUES的参数类型
toStdFun([](int a, float b){}, float{}, int{} );
如果参数不是浮点数而是类/复合类型,则通过构造实例来牺牲性能 - 只是浪费。
语法RetType(Args ...)更自然,类似于std::function<int(float,float)>
式
#include <utility>
#include <functional>
#include <iostream>
// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
// for pointers to member function
template <typename ClassType, typename RetType, typename... Args>
struct function_traits<RetType(ClassType::*)(Args...) const>
{
using signature_type = RetType (Args...); // strip the lambda class and use only operator signature
};
template <typename T>
auto make_function(T && t)
{
using signature = typename function_traits<T>::signature_type;
return std::function<signature>(std::forward<T>(t));
}
int main()
{
struct Typ {
Typ(int a) {
std::cout << "--CTOR--";
}
};
auto f = make_function([] (Typ t) {
});
std::cout << "BEFORE CTOR";
f(1); // perfect forwarding Ctor is called only once
std::cout << "AFTER CTOR";
}