【问题标题】:How to add a parameter value when forwarding parameters to a variadic template function?将参数转发到可变参数模板函数时如何添加参数值?
【发布时间】:2021-10-15 12:52:52
【问题描述】:

假设我下面有两个函数,在Foo()函数中,如何将hw字符串打包成args转发给Bar()

我试过std::bind,但没用。

template<typename T, typename... Args>
void Bar(Args&&... args) 
{
    // do something with args
}

template<typename T, typename... Args>
void Foo(Args&&... args)
{
    if (typeid(T) == typeid(std::string)) {
        std::string hw = "Hello, world!";
        Bar<T>(std::forward<Args>(hw, args)...);  // how to add hw to the forward list?
    }
    else {
        Bar<T>(std::forward<Args>(args)...);
    }
}

编辑:我终于找到了我的错误!对于那些想知道为什么hw 没有被转发到Bar() 的人,即使你做得对,请注意else 分支中的Bar()。如果Bar() 需要不同类型的参数,具体取决于T,并且代码无法编译,则else 分支可能会发出编译器错误。正如@JeJo 提到的,我应该改用if constexpr

您可能会发现这篇文章很有帮助: using std::is_same, why my function still can't work for 2 types

【问题讨论】:

    标签: c++ templates c++17 perfect-forwarding function-templates


    【解决方案1】:

    如何将hw添加到转发列表中?

    简单

    Bar<T>(hw, std::forward<Args>(args)...); 
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    或者如果您想将hw 移动到Bar()

    #include <utility>      // std::move, std::forward
    
    Bar<T>(std::move(hw), std::forward<Args>(args)...); 
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    或者让编译器推导出类型T

    Bar(std::move(hw), std::forward<Args>(args)...); 
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    为此,Bar 不需要第一个模板参数T

    template<typename... Args>
    void Bar(Args&&... args) 
    {
        // ....
    }
    

    话虽如此,您可能希望使用if constexpr 更改正常的 if 语句以进行编译时分支,如下所示:

    #include <utility>      // std::move, std::forward
    #include <type_traits>  // std::is_same_v
    
    template<typename T, typename... Args>
    void Foo(Args&&... args) 
    {
        if constexpr (std::is_same_v<T, std::string>)
        {
            std::string hw = "Hello, world!";
            Bar(std::move(hw), std::forward<Args>(args)...);  
        }
        else
        {
            Bar(std::forward<Args>(args)...);
        }
    }
    

    这里是complete demo

    【讨论】:

    • 也许 OP 想移动 hw?因为他们正试图将其添加到std::forward
    • @neo-mashiro 通过Bar(std::move(hw), std::forward&lt;Args&gt;(args)...);,您通过转发参考收到Bar() 的参数。您可以从此处进一步转发到任何其他功能。顺便你也可以Bar(std::forward&lt;T&gt;(hw), std::forward&lt;Args&gt;(args)...);
    • @Const 是的,你是对的,但是当我尝试将 hw 更改为指向另一个对象的指针时,代码将无法编译,看起来指针在中途完全丢失了,它是没有按预期转发,有什么想法吗?
    • @neo-mashiro 您不需要转发指针(不是智能指针),只需让它复制即可。
    • 非常感谢,直到你提到它,我才意识到if constexpr 是我真正的问题。将if改为if constexpr后,代码编译成功。我想知道为什么即使我通过了hwif 语句中的Bar() 也无法编译,但实际上真正抱怨的是else 分支中的Bar() ......我要追查的一个讨厌的错误!
    【解决方案2】:

    您需要将 hw 作为 std::move(hw) 单独传递给 Bar 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 2021-06-04
      • 2011-07-31
      • 2011-08-26
      • 2014-10-20
      相关资源
      最近更新 更多