我正在寻找一个类似于 memcpy 的现有函数,可以告诉它复制 x 字节,然后跳过 y 字节,重复直到复制了指定数量。
想象一个带有数据的缓冲区:
AABAAB
(我使用了字符,但我正在操作的数据不是字符串数据)。
当应用于此缓冲区并被告知复制 2 个字节并跳过 1 个字节时,目标缓冲区将包含:
AAAA
。
我还没有通过 STL 和 Boost 找到任何东西,但我希望其中有一些我错过的东西。
或者也许有一种聪明(而不是讨厌)的方法来使用更常见的函数来实现同样的事情。
boost::adaptors::strided
。
你可能会写这样的东西:
boost::copy(boost::make_iterator_range(in, in+size) | boost::adaptors::strided(2), out);
虽然这会产生大量的程序集,但它似乎也可以被编译器完美内联:编译器资源管理器示例。
boost::adaptors::filtered
,并使用不允许每个第 n 个元素的谓词(strided
执行相反的操作并保留每个第 n 个元素):
char const* input = "AABAAB";
unsigned counter{};
auto pred = [&counter](auto const&){ return ++counter % 3; };
boost::copy(boost::make_iterator_range(input, input+strlen(input)) | boost::adaptors::filtered(pred),
std::ostream_iterator<char>(cout));
实例;
似乎没有直接相当于 memcpy 来完成我想做的事情。 Boost 似乎经常有一些有用的辅助函数,但我最终实现了一个简单的循环函数来完成这项工作,因为它似乎是最简单和最合适的解决方案。
使用
chunk
、transform
和 take
,这是可能的:
data | std::views::chunk(N) | std::views::transform(std::views::take(M));
data | std::views::chunk(N)
:创建一系列范围,其中每个范围都是N个元素长
data | std::views::chunk(N) | std::views::transform(...);
:将 ...
应用于范围内的每个范围
data | std::views::chunk(N) | std::views::transform(std::views::take(M));
:取每个chunk的前M个元素作为范围。
例如
#include <fmt/ranges.h>
#include <array>
#include <ranges>
int main()
{
std::array data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
auto data_view = data | std::views::chunk(4) | std::views::transform(std::views::take(3));
fmt::println("{}\n", data_view);
}
// [[1, 2, 3], [5, 6, 7], [9, 0]]