我想将我的代码概括为采用std::span而不是std::vector作为参数,但不会失去传入 a 时获得的自动转换的便利性std::vector(请参阅如何将 std::vector 转换为 std::span?)。
然而,有问题的函数是在元素类型上模板化的——我在use_span_t下面得到了编译失败的信息。
void use_span(std::span<const double>) {}
template <typename T>
void use_span_t(std::span<const T>)
{
}
const std::vector<double> v{1, 2, 3};
use_span(v); // ok
use_span_t(v); // candidate template ignored: could not match 'span' against 'vector' (clang16)
use_span_t<double>(v); // ok
Run Code Online (Sandbox Code Playgroud)
我做错了什么,是否有一种解决方法,它不涉及调用站点(use_span_t<double>)的显式类型,或者在被调用站点上不涉及以下内容。
template <typename T>
void use_span_t(const std::vector<T>& v)
{
use_span_t(v);
}
Run Code Online (Sandbox Code Playgroud)
这个函数模板基本没什么用:
template <typename T>
void use_span_t(std::span<const T>);
Run Code Online (Sandbox Code Playgroud)
因为它不仅不接受vector<double>orvector<double> const正如您所看到的,它甚至不接受span<double>. 准确地说,它接受一个span<double const>. 这是非常有限的。如果有一种方法可以实现这一点那就太好了,但是......
在那之前,如果您想要做的是推断T任何连续范围并获得跨度T const,则必须这样做:
template <typename T>
void f(std::span<const T>);
template <std::ranges::contiguous_range R>
requires std::ranges::sized_range<R>
void f(R&& r) {
f(std::span<const std::ranges::range_value_t<R>>(r));
}
Run Code Online (Sandbox Code Playgroud)
任何contiguous+sized都可以转换为span,我们只需明确地执行即可。range_value_t<R>为我们提供了值类型(适用double于vector<double>和const vector<double>),因此我们可以使用它来构造正确的span。
如果我们已经使用fa进行调用span<T const>,则会选择第一个重载。任何其他内容,包括span<T>(对于非const T),都会选择第二个,然后转发到第一个。
差不多两年前,我还写了一篇关于强制深度常量的文章。
| 归档时间: |
|
| 查看次数: |
747 次 |
| 最近记录: |