在完美转发中,`decltype(std::forward<Args>(args))...` 和 Args&& 之间有什么区别
In perfect forwarding what is the difference between `decltype(std::forward<Args>(args))...` and 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(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([] () {});
}
两个样本有什么区别?
std::forward<T>
只是将 &&
添加到类型 T
并在用于转发参数时应用引用折叠规则。 Args&&...
也是
所以恕我直言,decltype(std::forward<Args>(args))...
和 Args&&...
是一样的。
我建议您使用另一种语法。
您的代码需要在 toStdFun
的 lambda 之后以逗号分隔列表形式将参数类型作为 VALUES
toStdFun([](int a, float b){}, float{}, int{} );
如果参数不是浮点数而是 classes/composite 类型,您将通过构造实例来牺牲性能 - 只会被浪费。
语法 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";
}
今天在学习完美转发,创建了这个代码示例
#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([] () {});
}
两个样本有什么区别?
std::forward<T>
只是将 &&
添加到类型 T
并在用于转发参数时应用引用折叠规则。 Args&&...
所以恕我直言,decltype(std::forward<Args>(args))...
和 Args&&...
是一样的。
我建议您使用另一种语法。 您的代码需要在 toStdFun
的 lambda 之后以逗号分隔列表形式将参数类型作为 VALUEStoStdFun([](int a, float b){}, float{}, int{} );
如果参数不是浮点数而是 classes/composite 类型,您将通过构造实例来牺牲性能 - 只会被浪费。
语法 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";
}