Довольно общим решением вашей проблемы было бы следующее (рабочий пример):
#include <iostream>
#include <vector>
using namespace std;
template<typename It, typename MemberType, typename Cond, typename Do>
void process_filtered(It begin, It end, MemberType iterator_traits<It>::value_type::*ptr, Cond condition, Do process)
{
for(It it = begin; it != end; ++it)
{
if(condition((*it).*ptr))
{
process((*it).*ptr);
}
}
}
struct Data
{
int x;
int y;
};
int main()
{
// thanks to iterator_traits, vector could also be an array;
// kudos to @Yakk-AdamNevraumont
vector<Data> lines{{1,2},{4,3},{5,6}};
// filter even numbers from Data::x and output them
process_filtered(std::begin(lines), std::end(lines), &Data::x, [](int n){return n % 2 == 0;}, [](int n){cout << n;});
// output is 4, the only x value that is even
return 0;
}
Это не использует STL, это правильно, но вы просто передаете пару итераторов, член для поискаи две лямбда-функции / функции, которые будут сначала фильтровать, а затем использовать отфильтрованный вывод соответственно.
Мне нравятся ваши общие решения, но здесь вам не нужно иметь лямбду, которая извлекает соответствующий атрибут.
Ясно, что код может быть улучшен для работы с const_iterator
, но для общей идеи, я думаю, это должно быть полезно.Вы также можете расширить его, чтобы иметь функцию-член, которая возвращает атрибут-член вместо прямого указателя на атрибут-член, если вы хотите использовать этот метод для инкапсулированных классов.