gpt4 book ai didi

c++ - boost::transform_iterator 和 std::iter_swap

转载 作者:搜寻专家 更新时间:2023-10-31 01:28:31 26 4
gpt4 key购买 nike

我正在尝试概括一个函数,该函数用于将两个迭代器带入特定数据结构的 vector ,并使用 std::iter_swap 以特定方式重新排列元素(就像 std::sort 那样)。

由于这个函数实际上只需要数据的一个子集,而我以后需要在其他上下文中使用它,所以我想到了去除对数据结构的依赖,并使用boost::transform_iterator 在处理转换的调用点。

不幸的是,boost::transform_iterator 似乎对这个变化不满意。我可以想象为什么:std::iter_swap 通常实现为 std::swap(*lhs, *rhs),并取消引用 transform_iterator不会产生要以正确方式交换的原始元素。

我想知道是否有办法处理这种情况。如果需要,我愿意使用 boost::range 或实验性 std::ranges ts。

这个问题可能类似于this one ,但即使在那里,解决方案最终也会修改算法所需的数据子集,而不是外部结构。

这是一个 MWE:

#include <boost/iterator/transform_iterator.hpp>
#include <vector>
#include <algorithm>
#include <iostream>

struct A {
int x;
int y;
};

template <typename It>
void my_invert(It begin, It end) {
while (begin < end) {
std::iter_swap(begin++, --end);
}
}

template <typename It>
void my_print(It begin, It end) {
for (; begin != end; ++begin)
std::cout << (*begin) << ' ';
std::cout << '\n';
}

int main() {
std::vector<int> x{7,6,5,4,3,2};

my_invert(std::begin(x), std::end(x));
my_print(std::begin(x), std::end(x));

auto unwrap = +[](const A & a) { return a.x; };

std::vector<A> y{{9,8}, {7,6}, {5,4}, {3,2}};

auto begin = boost::make_transform_iterator(std::begin(y), unwrap);
auto end = boost::make_transform_iterator(std::end(y), unwrap);

//my_invert(begin, end); // Does not work.
my_print(begin, end);

return 0;
}

最佳答案

访问底层迭代器

您可以访问 base() transform_iterator 的属性(从 iterator_adaptor 公开继承)来实现您的自定义 transform_iter_swap,用于交换包装迭代器的基础数据。

例如:

template<class IteratorAdaptor>
void transform_iter_swap(IteratorAdaptor a, IteratorAdaptor b)
{
std::swap(*a.base(), *b.base());
}

template <typename It>
void my_invert(It begin, It end) {
while (begin < end) {
transform_iter_swap(begin++, --end);
}
}

之后您的示例(省略 std::vector 部分)按预期运行:

my_invert(begin, end); // OK
my_print(begin, end); // 3 5 7 9

如果你想要一个通用的函数模板来覆盖 boost(适配器)迭代器和典型的迭代器,你可以例如根据迭代器 public typedef iterator_category 是否派生自 boost::iterators::no_traversal_tag 使用 if constexpr (C++17) 与否:

// expand includes with
#include <boost/iterator/iterator_categories.hpp>

template <class It>
void iter_swap(It a, It b) {
if constexpr(std::is_base_of<
boost::iterators::no_traversal_tag,
typename It::iterator_category>::value) {
std::swap(*a.base(), *b.base());
}
else {
std::swap(*a, *b);
}
}

template <typename It>
void my_invert(It begin, It end) {
while (begin < end) {
iter_swap(begin++, --end);
}
}

关于c++ - boost::transform_iterator 和 std::iter_swap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52021673/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com