提问人:resnet 提问时间:1/27/2022 最后编辑:resnet 更新时间:1/28/2022 访问量:741
有什么方法可以欺骗 std::transform 自己在迭代器上操作吗?
Any way to trick std::transform into operating on the iterator themselves?
问:
所以我写了这个代码,它不会编译。我认为原因是因为,当给定这样的迭代器范围时,将对迭代器指向的类型进行操作,而不是迭代器本身。是否有任何简单的包装器、标准库工具等可以使此代码工作,即将原始映射的所有迭代器存储到一个新的向量中,并且需要最少的更改?谢谢!std::transform
#include <map>
#include <iostream>
#include <vector>
using MT = std::multimap<char, int>;
using MTI = MT::iterator;
int main()
{
MT m;
m.emplace('a', 1); m.emplace('a', 2); m.emplace('a', 3);
m.emplace('b', 101);
std::vector<MTI> itrs;
std::transform(m.begin(), m.end(), std::back_inserter(itrs), [](MTI itr){
return itr;
});
}
编辑 1:无法使用 gcc11 和 clang13、C++17/20 编译
编辑2:这个问题的目的主要是出于好奇。我想看看有什么好方法可以操纵现有的标准算法,使其在我想要的水平上工作。示例代码和问题完全是为了演示而编造的,但它们与任何需要解决方案的实际问题无关
答:
0赞
463035818_is_not_an_ai
1/27/2022
#1
您传递给的函数和算法通常应该使用元素而不是迭代器。您可以使用该键在地图中查找迭代器,尽管这既不高效也不简单。请改用普通循环:std::transform
for (auto it = m.begin(); it != m.end(); ++it) itrs.push_back(it);
2赞
StoryTeller - Unslander Monica
1/27/2022
#2
有这样的包装器吗?不在标准中。但这并不意味着你不能写一个,即使是相当简单的。
template<typename It>
struct PassIt : It {
It& operator*() { return *this; }
It const& operator*() const { return *this; }
PassIt & operator++() { ++static_cast<It&>(*this); return *this; }
PassIt operator++(int) const { return PassIt{static_cast<It&>(*this)++}; }
};
template<typename It>
PassIt(It) -> PassIt<It>;
这只是包装器的示例1,它是指定模板参数类型的迭代器。它委托给其基础进行记账,同时确保返回类型符合在取消引用时返回包装迭代器本身。
您可以在示例中使用它来简单地复制迭代器
std::copy(PassIt{m.begin()}, PassIt{m.end()}, std::back_inserter(itrs));
(1) - 它依赖于推导出正确的东西。如本例所述,它可能不符合规定的迭代器类型的所有要求(在本例中,我们针对的是前向迭代器)。如果发生这种情况,将需要更多的样板。std::iterator_traits
评论
0赞
resnet
1/28/2022
谢谢你,正是我正在寻找的那种答案。欣赏完整的模板演示
0赞
jian
2/26/2022
嗨,实时链接已损坏。我不知道如何坚持到底。以下代码不起作用。godbolt.org/z/cTxs8MhzT 您介意分享完整的代码。
0赞
StoryTeller - Unslander Monica
2/26/2022
@Mark - 坏了,怎么坏的?它把我带到这个例子,并吐出预期的输出。你的示例不起作用,因为你尝试将迭代器插入到整数向量中。将您的代码与 OP 进行比较。
0赞
jian
2/26/2022
@StoryTeller-UnslanderMonica:我猜网站已经关闭了。无论如何,谢谢......
评论
*r = o