c++ - 通过外部评估调度将标准兼容性与不透明数据连接起来

标签 c++ algorithm iterator std opaque-pointers

我正在低级别接收托管数据{ void * data; uint 步幅,计数; } 格式。我可以读取、写入和交换数据项,但不能添加或删除/调整大小/重新分配。有足够的信息用于迭代和随机访问,但没有用于取消引用的类型信息。所有不透明的项目都可以轻松复制和移动。

在现代 C++ 中是否有可能促进这种数据格式的 std 兼容性,省略解引用接口(interface),并将评估委托(delegate)给外部上下文?像这样的东西:

std::sort(OpaqueFirst, OpaqueLast, [](Opaque a, Opaque b){ return handle(a, b); });

最佳答案

基本思想是创建一个引用您的子数组之一的类型并定义 swap实际交换它们的内容:

struct buffer {std::span<std::byte> s;};  // but see below

void swap(const buffer &a,const buffer &b) {
  assert(a.s.size()==b.s.size());
  auto i=b.s.begin();
  for(auto &x : a.s) std::swap(x,*i++);
}

然后我们只需要创建此类对象的惰性范围,这很容易使用 std::views::transform缠绕std::views::iota ,并根据问题写出简单的比较器:

struct array { void * data; uint stride, count; };

void sort(const array &a,bool lt(const void*,const void*)) {
  std::ranges::sort
    (std::views::transform
     (std::views::iota(uint(),a.count),
      [&](uint i)
      {return buffer{{static_cast<std::byte*>(a.data)+a.stride*i,a.stride}};}),
     [&](const buffer &x,const buffer &y) {return lt(x.s.data(),y.s.data());});
}

不幸的是,sort要求能够将范围元素移动到临时变量中,而不仅仅是交换它们。这需要一个相当复杂的包装类型,它实际上可以暂时拥有数据,这反过来又需要动态分配,因为 array::stride不是一个常数:

struct buffer {
  std::unique_ptr<std::byte[]> u;
  std::span<std::byte> s;

  buffer(std::span<std::byte> s) : s(s) {}
  buffer(buffer &&b) noexcept {
    if(b.u) u=std::move(b.u);
    else {
      u=std::make_unique<std::byte[]>(b.s.size());
      std::ranges::copy(b.s,u.get());
      s={u.get(),b.s.size()};
    }
  }

  void operator=(const buffer &b) const noexcept;
  buffer& operator=(const buffer &b) noexcept {
    assert(s.size()==b.s.size());
    std::ranges::copy(b.s,s.begin());
    return *this;
  }
};

保留我们的习惯swap避免对每个元素交换使用此类分配,因此性能并不糟糕。未实现的operator=(…) const有必要让图书馆相信 buffer是一种代理类型,应该支持通过纯右值排序。

一个complete example与完整buffer类型存在于编译器资源管理器中。

关于c++ - 通过外部评估调度将标准兼容性与不透明数据连接起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77774335/

相关文章:

c++ - 如何在 C++ 中一起使用 setw 和 setfill 来填充空格和字符?

c++ - 使用字符串化运算符将字符串值而不是 const 字符串文字传递给宏

php - 构建C++共享库,.so被激活,等待PHP网页调用

c# - 如何合并多个序列

c++ - 遍历 C++ 中的字符串列表,出了什么问题?

c++ - 按字典顺序从范围中获取下一个数字(没有所有字符串化的容器)

c++ - 将函数的默认参数设置为数组

arrays - Swift - 在数组中搜索数字模式

algorithm - 从样本的 3 维矩阵中确定 3D "contour-esque"形状

c++ - 如何跟踪 C++ vector 上的当前和上一个迭代器?