【问题标题】:Is there a way to expand and call a tuple of std::functions?有没有办法扩展和调用 std::functions 的元组?
【发布时间】:2019-12-10 21:57:22
【问题描述】:

我有一个包含函数元组的类,它们的返回类型由类的模板确定:

template <typename... Ts>
class A{
    static inline auto funcs = std::make_tuple(std::function<Ts()>()...)
};

我希望能够迭代这些函数。我尝试使用以下答案中的方法从模板中获取每种类型的索引:https://stackoverflow.com/a/26169248/

std::get<Index<Ts,Ts...>::value>(funcs)()...;

但是这段代码无法编译。它在末尾抱怨“...”,可能是因为当我键入“T...”时模板参数包已经展开,但我不明白为什么它不会让我展开其他“Ts” ”。有没有办法做到这一点?

【问题讨论】:

  • 您使用的是什么 C++ 版本?如果 17:尝试在 ... 之前添加 ,
  • 我使用的是 C++17。添加逗号似乎没有任何作用——我在 GCC 和 MSVC 中都尝试过。 MSVC 的错误是“unexpected token '...', expected expression”,而 GCC 的错误是“expected ';'在 '...' 标记之前"

标签: c++ templates tuples variadic-templates std-function


【解决方案1】:

您必须在您的funcs 分配中删除{},否则这将创建一个initializer_list 而不是tuple

static inline auto funcs = std::make_tuple(std::function<Ts()>()...);

然后,您可以在 std::apply 和通用可变参数 lambda 的帮助下调用每个元组函数:

auto call = [](auto&&...funcs) {
    (funcs(),...);
};

int main()
{
    A<int, float, char> l;
    std::get<0>(l.funcs) = []() { cout << "Calling int()" << endl; return 1; };
    std::get<1>(l.funcs) = []() { cout << "Calling float()" << endl; return 1.f; };
    std::get<2>(l.funcs) = []() { cout << "Calling char()" << endl; return '1'; };

    std::apply(call, l.funcs);
    return 0;
}

查看实时示例:https://onlinegdb.com/HJfQ95TpS

【讨论】:

  • 谢谢,这行得通!我有点好奇为什么它必须是一个通用的 lambda,为什么像 @n314159 这样的建议不起作用?
  • 他的建议确实有效,但您必须像我在调用函数stackoverflow.com/a/33868734/7908019 中所做的那样用括号括起表达式。如果我使用可变参数模板而不是通用 lambda,我们将不得不在调用 std::apply 时指定模板参数,即 std::apply(call<:function>&>...);看看onlinegdb.com/BylOWoaaS
  • 非常有趣!假设我们想将返回值存储在一个元组中,我们将如何将它们从 std::apply 中取出?如果我们使用可变参数模板,这似乎更简单。像这样的东西,虽然当你要求多种类型时它不会编译,我不明白为什么:onlinegdb.com/H1p3cop6S
  • 去掉 , 和括号,在分配元组 onlinegdb.com/Hy4wOxkRr 的函数时也修复索引。
猜你喜欢
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-30
  • 2012-04-02
相关资源
最近更新 更多