在查看 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++ 模板为每组模板参数创建新函数。这正是为什么
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()
的模板参数推导。这就是它起作用的原因。