微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用用户定义的概念作为 std::span 的模板类型?

如何解决如何使用用户定义的概念作为 std::span 的模板类型?

我想使用我的用户定义概念作为 std::span 的模板类型,但模板参数推导没有按我预期的那样工作。当我尝试将“std::array of char”传递给模板函数时;编译器显示错误error: no matching function for call to 'print'”并在我用鼠标将鼠标悬停在模板定义上时警告我“注意:候选模板被忽略:无法匹配'span' 对 'array'"

这里是概念定义和函数模板:

#include <concepts>
#include <span>

template <typename  T>
concept OneByteData = sizeof(T) == 1;

template<OneByteData T>
void print(std::span<const T> container)
{
    for(auto element : container)
    {
        //Do Some Work
    }
}

以及无法按我预期工作的用户代码

int main()
{
    std::array<char,6> arr = {1,2,3,4,5,6};
    print(arr);
    return 0;
}

有效且不会产生错误用户代码

int main()
{
    std::array<char,6};
    print<char>(arr);
    return 0;
}

有没有办法在不专门化数组类型的情况下调用这个模板函数。我应该如何更改模板函数定义以按照我提到的方式调用函数 (print(arr))?

编辑:我希望能够利用 std::span 的好处,并且能够使用 std::array、std::vector 和普通 C 样式调用模板函数数组。

解决方法

一个可能的解决方案是接收(并推导出)一个泛型类型,然后检查它是否可以转换为 std::span 大小为 1 的 element_type

我是说

template <typename  T>
concept OneByteData = sizeof(T) == 1;

template <typename T>
void print (T container) 
   requires OneByteData<typename decltype(std::span{container})::element_type>
{
  std::span cnt {container};
  
    for(auto element : cnt )
    {
        //Do Some Work
    }
}

// extra print for C-style cases
template <typename T,std::size_t N>
void print (T(&arr)[N])
{ print(std::span{arr}); }

另一种可能的解决方案是 print(),类似于您的原始解决方案,它接收 std::span 并进行概念检查,以及一些额外的 print()(一个特定于 C 样式数组)将推导出的类型转换为 std::span

template <typename  T>
concept OneByteData = sizeof(T) == 1;

template<OneByteData T,std::size_t N>
void print(std::span<T,N> container)
{
    for(auto element : container)
    {
        //Do Some Work
    }
}

template <typename T,std::size_t N>
void print (T(&arr)[N])
{ print(std::span{arr}); }

template <typename T>
void print (T container)
 { print(std::span{container}); }
,

From my understanding 这是您实际应该如何使用它:

// Second template parameter for size
template<OneByteData T,N> container) {
  // Do something
  return;
}

// Create a span from a plain array
print(std::span{arr});

Try it here


如果你不希望你的用户自己做,你可以

  • print 编写一个重载来处理从 std::arraystd::span 的转换,例如 (Wandbox)

    template<OneByteData T,std::size_t N>
    void print(std::array<T,N> const& container) {
      return print<T const>(std::span{container});
    }
    
  • 否则,您可以重写 print 的接口以获取任何容器,使用 {{1} 强制对底层元素类型进行约束} 或用户 max66 等概念提出并在内部将这个通用容器转换为 std::enable_if

  • 对于,您可以编写一个模板推导指南,它决定应该使用哪个构造函数 (Wandbox)

    std::span

编辑

对于像评论中讨论的那样的运算符,我实际上会使用模板化函数和模板化运算符的组合。函数 template <typename T,std::size_t N> Print(std::array<T,N>) -> Print<T,N>; 使用泛型 append 来处理 std::span 数据类型,而模板运算符将允许的数据类型转换为 OneByteData 并调用该函数。 std::span 确保可以将数据结构转换为具有正确数据类型的 OneByteData<typename decltype(std::span{cont})::element_type>。您可以为其添加额外的或不同的约束,或者将这些约束与您自己的概念结合起来。

std::span

试试 herehere

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?