在完美转发中,`decltype(std :: forward <args>(args))...和Args&amp;&amp;

时间:2015-08-14 20:55:56

标签: c++ c++11 c++14 std-function perfect-forwarding

今天我正在学习完美转发,我创建了这个代码示例

#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([] () {});

    }

两个样本之间有什么区别?

2 个答案:

答案 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";
}