【问题标题】:Forwarding variadic list of arguments转发可变参数列表
【发布时间】:2019-10-31 23:43:01
【问题描述】:

以下两个代码都按预期编译和执行,它们有什么不同吗?

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;
}

看着SO How would one call std::forward on all arguments in a variadic function?,似乎推荐第二个,但第一个不也是这样做的吗?

【问题讨论】:

    标签: c++ c++11 templates c++14 perfect-forwarding


    【解决方案1】:

    它们不一样。在args的arity为1或0的情况下都是一样的,否则编译失败,考虑一下..

    #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;
    }
    

    Demo

    对于失败的情况,std::forward&lt;U...&gt;(args...) 扩展为 forward&lt;int, int&gt;(int&amp;, int&amp;) 并且将无法编译。

    std::forward&lt;U&gt;(args)... 扩展为 std::forward&lt;int&gt;(int&amp;),std::forward&lt;int&gt;(int&amp;)

    【讨论】:

    • 所以 forward 只能接受一个模板参数?
    • 是的,正确的,请看这里 -> en.cppreference.com/w/cpp/utility/forward
    • 既然你传递的是一个临时的,它不应该扩展到转发(int&&, int&&),我是不是误会了
    • 它现在是一个命名的临时文件。在 time_function 中,int 都是名为 args 的命名参数包的一部分。这是 std::forward 的重点。在这种情况下,它会将其转换回 int&&
    • 这可能会弄清楚发生了什么。下面示例中的重要一点是,在每种情况下 U 不只是 'int',如果它是左值,它将是 int& 并且引用折叠规则适用 @987654323 @。这应该让您了解 'std::forward 知道是否要转换'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 2013-01-06
    • 2017-06-10
    相关资源
    最近更新 更多