为什么 std::apply 使用函数模板会失败,但使用具有显式模板参数列表的 lambda 表达式却不会失败? [重复]

问题描述 投票:0回答:1

在查看 cpprefrence 中的 std::apply 引用时,我们可以看到函数模板不能作为 std::apply 的可调用对象传递。让我们考虑以下函数模板:

template<typename T>
T add_generic(T first, T second) { return first + second; }

因此,由于在 std::apply 调用中无法推导出函数模板,因此我们不能使用以下代码:

std::apply(add_generic, std::make_pair(2.0f, 3.0f)); // Error: can't deduce the function type

请注意,这与这个问题不是同一个问题。在该答案中,作者编写了一个没有显式模板参数的 lambda 表达式。

std::cout << std::apply(
    [](auto first, auto second) { return add_generic(first, second); },
    std::make_tuple(2.0f,3.0f)) << '\n';

但是正如您在 c++20 中所知,您可以使用带有显式模板参数列表的 lambda 表达式。所以我尝试了这个功能,令人惊讶的是编译器没有引发任何错误。

std::apply([]<typename T>(T first,T second){
    return first+second;
},std::make_pair(2.0,3.0));

为什么编译器能够在最后一种情况下推断出类型?两者有什么区别吗

c++ lambda
1个回答
7
投票

函数模板不是函数,就像饼干模具不是饼干一样。 C++ 模板为每组模板参数创建新函数。这正是为什么

add_generic
不是一个可行的论点。它不是一个函数,它不能作为值传递。为了获得该函数,编译器需要推导模板参数。但它只能在可调用对象被传递之后
apply
after内执行此操作。先有鸡还是先有蛋。

为什么 lambda 有效?因为它也不是一个简单的函数。它产生一个隐藏的对象类型

struct __lambda_at_line_N {
  template<typename T>
  auto operator()(T first, T second) { /* ... */ }
};

并通过了那个

std::apply(__lambda_at_line_N{},std::make_pair(2.0,3.0));

这是一个实际的对象,一个值。它的类型不依赖于需要在

std::apply
内部发生以调用
operator()
的模板参数推导。这就是它起作用的原因。

© www.soinside.com 2019 - 2024. All rights reserved.