在查看cpprefrence中的 std::apply 引用时,我们可以看到函数模板不能作为 std::apply 的可调用对象传递。让我们考虑以下函数模板:
template<typename T>
T add_generic(T first, T second) { return first + second; }
Run Code Online (Sandbox Code Playgroud)
因此,由于无法在 std::apply 调用中推导函数模板,因此我们不能使用以下代码:
std::apply(add_generic, std::make_pair(2.0f, 3.0f)); // Error: can't deduce the function type
Run Code Online (Sandbox Code Playgroud)
请注意,这与这个问题不是同一个问题。在该答案中,作者编写了一个没有显式模板参数的 lambda 表达式。
std::cout << std::apply(
[](auto first, auto second) { return add_generic(first, second); },
std::make_tuple(2.0f,3.0f)) << '\n';
Run Code Online (Sandbox Code Playgroud)
但正如您所知,在c++20中,您可以使用带有显式模板参数列表的 lambda 表达式。所以我尝试了这个功能,令人惊讶的是编译器没有引发任何错误。
std::apply([]<typename T>(T first,T second){
return first+second;
},std::make_pair(2.0,3.0));
Run Code Online (Sandbox Code Playgroud)
为什么编译器能够在最后一种情况下推断出类型?两者有什么区别吗?
函数模板不是函数,就像饼干模不是饼干一样。C++ 模板为每组模板参数创建新函数。这正是为什么这add_generic不是一个可行的论点。它不是一个函数,它不能作为值传递。为了获得该函数,编译器需要推导模板参数。但它只能在可调用对象传递apply 之后在内部执行此操作。鸡和蛋就在那里。
为什么 lambda 有效?因为它也不是一个简单的函数。它产生一个隐藏对象类型
struct __lambda_at_line_N {
template<typename T>
auto operator()(T first, T second) { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
并通过了
std::apply(__lambda_at_line_N{},std::make_pair(2.0,3.0));
Run Code Online (Sandbox Code Playgroud)
这是一个实际的对象,一个值。std::apply它的类型不依赖于调用内部需要发生的模板参数推导operator()。这就是它起作用的原因。
| 归档时间: |
|
| 查看次数: |
396 次 |
| 最近记录: |