在完美转发中,`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";
}