提问人:FrankM 提问时间:9/1/2023 最后编辑:Jan SchultkeFrankM 更新时间:9/13/2023 访问量:283
为什么在传递 std::vector 时不能为 std::span<T> 推断 T?
Why can T not be deduced for std::span<T> when passing a std::vector?
问:
在下面的 C++20 代码中,将 传递给带有参数的模板化函数会失败,因为编译器显然无法推断模板参数。我已经用 GCC、Clang 和 MSVC 尝试过了;都失败了。std::vector
std::span<T>
像这样调用有效:或 .f3(std::span(vi))
f3(std::span(vp))
我想知道为什么会失败,因为在我的理解中,是一个范围,并且有一个范围的推导。std::vector
std::span
#include <memory>
#include <vector>
#include <span>
void f1(std::span<int> s)
{
}
void f2(std::span<std::shared_ptr<int>> s)
{
}
template<typename T>
void f3(std::span<T> s)
{
}
int main(int argc, char* argv[])
{
std::vector<int> vi;
std::vector<std::shared_ptr<int>> vp;
f1(vi);
f2(vp);
f3(vi); // ERROR: no matching function for call to 'f3'
f3(vp); // ERROR: no matching function for call to 'f3'
return 0;
}
答:
如果函数参数参与模板参数推导,则不允许对该函数参数进行隐式转换。
评论
T &&range
std::span<??>
template <typename T> void f3(foo<T>)
foo
不幸的是,你要做的事情是不可能的。在通话中....
template<typename T> void f3(std::span<T> s) { /* ... */ } // [...] std::vector<int> vi; f3(vi);
...不是 ,因此无法从中推导出模板参数。函数模板参数推导不考虑隐式转换。std::vector
vi
std::span
T
您已经指出有一个扣除指南,但该功能不能在这里使用:
当模板名称显示为推导类类型的类型说明符时,将使用推导指南。
- [温度扣除指南]
这意味着 std::span
推导指南......
template< class R > span( R&& ) -> span<std::remove_reference_t<std::ranges::range_reference_t<R>>>;
...可用于以下场景:
f3(std::span(vi));
// or
std::span s = vi;
无论哪种情况,这都会形成一个 .std::span<int>
溶液
总的来说,这是一个众所周知且非常烦人的局限性。如果你想要一个“通用范围”,惯用的解决方案是接受一个受约束的范围:std::span
#include <ranges>
template <std::ranges::contiguous_range R>
requires /* TODO: additional constraints for the range value type? */
void foo(R&& r) {
// ...
}
由于您无论如何都在编写函数模板,因此制作一个接受任何 std::ranges::contiguous_range
的模板与编写一个只接受 .std::span
大多数情况下,您可以使用更宽松的范围要求,例如 std::ranges::forward_range
。
我想知道为什么这失败了,因为在我的理解中,是一个范围,并且有一个扣除指南 范围。
std::vector
std::span
这个答案解释了为什么这不起作用。如果您仍想工作,可以通过检查类型是否启用以下类型的扣除指南来实现:f3(vi)
R
std::span
#include <span>
template<class R>
requires requires(R&& r) { std::span(std::forward<R>(r)); }
void use_as_span(R&& r) {
std::span sp(std::forward<R>(r));
// use span here
}
评论