【问题标题】:C++: How call a function with type parameter on variadic template arguments?C++:如何在可变参数模板参数上调用具有类型参数的函数?
【发布时间】:2021-04-10 17:58:17
【问题描述】:

所以我有一个带有可变模板参数的函数,我试图为每个参数调用一个方法(带有一个类型参数),将每个结果值打包到 std::tuple 中并返回它。然而,可变参数模板对我来说很难,我还没有完全理解它们。

甚至有可能在 C++ 中实现这一点吗?

到目前为止,这是我的代码(getMultiple 函数中有错误)。非常感谢您的帮助!

#include <iostream>
#include <fstream>
#include <sstream>

template<typename T>
T get(std::istream &stream) {
    T data;
    stream >> data;
    return data;
}

template<typename ... Ts>
std::tuple<Ts...> getMultiple(std::istream &stream) {
    // What am I doing wrong here?
    return std::make_tuple((get<Ts...>(stream)));
}

int main() {
    std::istringstream stream("count 2");
    auto [command, number] = getMultiple<std::string, int>(stream);

    return 0;
}

【问题讨论】:

    标签: c++ c++17 variadic-templates variadic-functions


    【解决方案1】:

    首先,你忘记了

    #include <tuple>
    

    您可能正在寻找的语法是:

    return std::make_tuple(get<Ts>(stream)...);
    

    【讨论】:

    • 这不太正确:对get 的调用是不确定的。您应该摆脱 make_tuple 并使用 return {get&lt;Ts&gt;(stream)...}; 调用构造函数
    【解决方案2】:

    您几乎是正确的,但您的 ... 放错了位置,

    get&lt;Ts...&gt;(stream) 转换为 get&lt;T0, T1, .., Tn&gt;(stream)

    应该是

    foo(get&lt;Ts&gt;(stream)...) 转换为 foo(get&lt;T0&gt;(stream), get&lt;T1&gt;(stream), .., get&lt;Tn&gt;(stream))

    您对评估顺序有疑问

    foo(a(), b())a()b() 中是不确定的,所以a() 可能发生在b() 之前,或者相反。可变参数模板不会改变这一点。

    所以你不能使用std::make_tuple。幸运的是,在{..} 内部,顺序是从左到右确定的,因此您可以使用:

    return std::tuple{get&lt;Ts&gt;(stream)...};

    【讨论】:

    • 我不会在return 中写std::tuple。我们已经知道函数声明返回的确切类型,所以只需 return {get&lt;Ts&gt;(stream)...}; 就可以了。这样我们就不必担心类模板参数推导得到正确的类型。
    • @HTNW 我同意它是多余的,但为什么 CTAD 获取类型正确会有任何问题?
    • @cigien 考虑简化template&lt;typename... T&gt; std::tuple&lt;T...&gt; do_something() { return std::tuple{T()...}; },然后调用do_something&lt;std::tuple&lt;int, int&gt;&gt;()。您是否立即看到这是如何工作的? std::tuple&lt;int, int&gt; 是默认构造的。写的std::tuple也推导出为std::tuple&lt;int, int&gt;,选择copy-construction。然后使用 this 作为其唯一元素构造返回值(使用“直接构造函数”)。当您可以写{Ts()...} 并立即明确表示它会起作用时,为什么还要介绍所有这些隐藏的步骤?
    猜你喜欢
    • 1970-01-01
    • 2021-10-01
    • 2013-06-24
    • 2023-04-02
    • 2012-07-10
    • 1970-01-01
    • 2015-08-09
    相关资源
    最近更新 更多