【问题标题】:I can't pass template funtion to std::apply directly but I can through lambda我不能直接将模板函数传递给 std::apply 但我可以通过 lambda
【发布时间】:2020-12-17 13:41:07
【问题描述】:

基于:How do I expand a tuple into variadic template function's arguments?

#include <string>  
#include <iostream>    
#include <tuple>  

template <typename... Args>
void print_all(const Args &... args) {
    ((std::cout << " " << args), ...) << std::endl;
}

int main()
{

    // Create a tuple
    auto values = std::make_tuple(1, 2, 3.4f, 4.5, "bob");
    
    // Need to pass the tuple through the lambda for template type deduction and to pass param to template function?
    std::apply([](auto &&... args) { print_all(args...); }, values);

    // This does not work - other then there is no parameter I can't see how this does not work
    // and how the lambda does work as it has the same (roughly) param list
    std::apply(print_all(), values);


    return 0;
}

有人能解释为什么一个有效而另一个无效吗?

【问题讨论】:

  • print_all() 是一个函数调用,但您不想调用该函数 - 您想传递它。它确实有效(使用正确的语法):Demo on coliru。不过,这里似乎没有类型推断。
  • 函数模板的这些实例的指针是不同的值,所以编译器不知道print_all应该衰减到什么。无论函数模板还是重载函数不是单态的,你都必须用函子或 lambda 包装它,给参数一个明确的类型。
  • @Scheff 对此表示感谢 - 这对我来说很有意义,但是(希望很明显)我不想传递所有模板类型! :)
  • @RedFog 我想我明白了——我一直在努力解决的是 lambda 是如何工作的,因为它具有相同的参数列表——但是下面的答案指出它更像一个 operator() 模板重载然后是一个函数模板(如果我理解正确的话)

标签: c++ templates tuples


【解决方案1】:

在幕后,这个 lambda 表达式[](auto &amp;&amp;... args) { print_all(args...); } 大致是以下类型:

 struct [unnamed] {
      template <typename ...Args>
      void operator()(Args&&...args) { ... };
 };

它是一个带有模板化operator() 的类型,即重载决议和模板参数删除仅在operator() 被实际调用时发生。另一方面,print_all 是一个模板,因此您不能将其传递给 std::apply

换句话说,无论Args... 是什么,lambda 始终是同一类型,但print_all 不是。您需要先实例化它,然后才能获得指向该函数的指针。正如 Scheff 所说,这很好:

std::apply(&print_all<int, int, float, double, const char*>, values);

【讨论】:

  • 哦,我明白了......所以如果我用模板 operator() 制作了一个结构(就像你做的那样),那么它会起作用 - 因此使用 lambda 是一个很好的技巧来解决这个问题 -谢谢!
猜你喜欢
  • 2022-06-12
  • 1970-01-01
  • 2021-12-28
  • 2017-03-07
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多