我在使用lambda传递谓词时遇到问题,我正在尝试将匹配谓词的元素移动到第二个容器的开头,但它似乎没有用,所以有什么问题呢?
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <utility>
#include <algorithm>
using namespace std;
template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
if(pred)
{
o.insert(o.begin(),pred);
}
}
int main()
{
vector<int>v{1,2,3,4,5,6,7,8,9,10};
vector<int>v2;
for (auto i=v.begin(); i !=v.end(); ++i)
save_if(v.begin(), v.end(), v2, []( vector<int>::iterator i){return (*i>5);});
return 0;
}
答案 0 :(得分:3)
试试这个......
int main()
{
std::vector<int> v{1,2,3,4,5,6,7,8,9,10};
std::vector<int> v2;
std::vector<int>::const_iterator
it = std::remove_copy_if(v.begin(), v.end(),
std::back_inserter(v2),
[](int const& i){return i <= 5;});
v.erase(it, v.end);
return 0;
}
您可以阅读有关remove_copy_if
on cppreference.com的更多信息;除非谓词返回true,否则它从输入范围中删除元素并将它们复制到输出中。
请注意,这是一个STL 删除,因此您需要在之后调用erase来缩小输入。此解决方案的语义与您发布的代码略有不同,但更类似于您对所需内容的描述。
答案 1 :(得分:2)
检查一下,我对你的代码进行了一些修改:
template <typename iterator, typename Container, typename T>
void move_if(iterator a, iterator b, Container &o, T pred)
{
for (auto i = a; i != b; i++)
{
if (pred(*i))
o.insert(o.begin(), *i);
}
}
int main()
{
vector<int>v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int>v2;
move_if(v.begin(), v.end(), v2, [](int i) { return !(i > 5); });
}
注意:作为评论,如果功能与上述代码相同,建议将move_if
重命名为copy_if
,否则您应该真正移动项目。
答案 2 :(得分:1)
没有std::vector::insert的重载将谓词作为第二个参数,所以这一行是错误的:
o.insert(o.begin(),pred);
此外,需要使用参数
调用谓词pred(someArg);
在您的情况下将是std::vector<int>::iterator
。此外,save_if
与move_if
不同。但更重要的是,目前尚不清楚你想要实现的目标。
答案 3 :(得分:1)
在C ++ 11中,像[](){return true}
这样没有捕获任何内容的无状态lambdas可以隐式转换为函数指针。执行if(pred)
时,您将无状态lambda转换为函数指针,检查该指针是否为非null(它是非null)。这不是你想要做的。
move
b
e
之间的pred(x)
template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
for( auto i = b; i != e;++i) {
if(pred) {
o.insert(o.end(),std::move(*i));
}
}
}
o.end()
{{}}} {{\ n} {{}}
Container
请注意,我在vector
处插入,因为您想要的end()
可能是vector
,而std::back_inserter
的{{1}}插入速度要快得多。
实际上,您可能想要使用输出迭代器(默认情况下,使用Container
中的remove_move_if
)并输出数据。同样,b
是一种更好的方法,可以删除e
- iterator
范围内的元素,并返回begin(c)
。
最后,基于范围的算法值得写。而不是采用开始/结束迭代器对,取一个已覆盖end(c)
和struct
的单个对象返回开始/结束。如果您正在处理子范围,则可以传入开始/结束范围的迭代器{{1}},并且适当地覆盖begin / end。