繁体   English   中英

标准::跨度<const t>作为 function 模板中的参数</const>

[英]std::span<const T> as parameter in function template

在下面的库函数fg中,我使用std::span<const T>来提醒合约库的用户fg不会修改 span 的内容。 该库的用户持有std::span<int> a ,可转换为std::span<const int> 因此,用户可以按预期调用g(a) 但是,用户不能调用f(a) ,因为f是 function 模板并且a不是所需的类型; 转换不适用于此处。 你能看到一种(理智的)方式让f接受std::span<const T>同时仍然接受std::span<T>吗?

#include <span>

void g(const std::span<const int>& a) {}

template <typename T>
void f(const std::span<const T>& a) {}

int main()
{
    std::span<int> a;
    // OK
    g(a);
    // No match
    f(a);
    // OK
    f((std::span<const int>)a);
}

可以像这样添加重载:

template <typename T>
void f(const std::span<T>& a) {
    return f((std::span<const T>)a);
}

但我不确定我是否认为这是理智的,从那时起我会将这些重载写入每个接受std::span<const T>的 function 模板。

编辑:不一样的情况,但如果f也碰巧接受另一个提到T的参数,那么可以执行以下操作:

template <typename T> using NoDeduction = std::type_identity_t<T>;

template <typename T>
void f(NoDeduction<std::span<const T>> a, const T& b) {}

之后f(a, 1); 作品。 这是部分解决方案。 原来的问题依然存在。

编辑 2:我想知道当我们包含 span 的编译时大小时,上述技术是否也有效:

template <typename T, std::size_t N>
void f(const std::span<NoDeduction<const T>, N>& a, const T& b) {}

Gcc 10.1 编译它,MSVC 16.6.2 和 Clang 10.0.0 不编译。 我提交了 MSVC 和 Clang 的错误报告。

您可以将您的重载概括为像std::as_const这样的实用程序

template<class T>
std::span<const T> const_span(std::span<T> s) {return s;}

然后调用者必须用可变跨度装饰他们的调用,但这样做会向读者表明不允许修改。

另一种非常规的解决方法是使您的 function 成为 class 并使用扣除指南

template<class T>
struct f {
  f(std::span<const T>);
  // operator ReturnType();
};
template<class T> f(std::span<T>)->f<T>;

接口是否描述了这里的意图是有争议的。

它无法进行类型转换,因为它无法推断类型,因为f是模板。

如果你想编写接受各种输入类型的模板 function f - 你最好把它写成

 template<typename Viewer>
 void f(const Viewer& a){...}

如果您想使用span ,那么您可以分两步实现它:

 template<typename T>
 void f_impl(std::span<const T> a){...}

 template<typename Viewer>
 void f(const Viewer& a)
 {
      f_impl(std::span<const typename Viewer::value_type>(a.data(),a.size()));
  }

PS with span你通常应该复制它而不是“const reference”。 这样更有效率。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM