I suggest Boost Range:
Live on coliru
int main() { myvec all_items = { { 151, "test1" }, { 154, "test4" }, { 152, "test2" }, { 151, "test1" }, { 151, "test1" }, { 153, "test3" } }; auto is_good = [bad_ids = std::set<int> { 151, 152 }](mystruct v) { return bad_ids.end() == bad_ids.find(v.id); };
Print
Good item: 154 Good item: 153
Improvement ...
You can improve the style by slightly changing the situation:
Assuming you have a utility like contains :
template <typename... Arg, typename V> bool contains(std::set<Arg...> const &set, V const &v) { return set.end() != set.find(v); } template <typename... Arg, typename V> bool contains(std::vector<Arg...> const &vec, V const &v) { return vec.end() != std::find(vec.begin(), vec.end(), v); }
Then it becomes more readable:
Live on coliru
auto is_good = [&bad_ids](auto& v) { return !contains(bad_ids, v.id); }; for (auto& f : all_items | filtered(is_good)) { std::cout << "Good item: " << f.id << std::endl; }
Now I feel that the entire list of bad_ids can also be dynamic. But if it is not, you can be more "in place" using Phoenix:
Peak Hipster:
Live on coliru
for (auto& f : all_items | filtered(!contains_(std::set<int> { 151, 152 }, arg1->*&mystruct::id))) { std::cout << "Good item: " << f.id << std::endl; }
I know. This pushes him for no good reason, but hey. Just show :)