Выполните итерацию по контейнеру структур по определенному элементу

#c #c 17

Вопрос:

У меня есть функция

 template<typename I> double mean(I begin, I end)
{
    double s = 0;
    size_t n = 0;
    while(begin != end)
    {
        s  = *begin  ;
          n;
    }
    
    return s / n;
}
 

и вектор структур T:

 struct T
{
    double a;
    double b;
};
vector<T> v;
 

Есть ли элегантный способ вычислить среднее значение всех a членов структур в v ? Какой-то способ обернуть vector<T>::iterator в итератор, который извлекает a элемент?

Комментарии:

1. boost::transform_iterator и std::ranges::views::transform с диапазоном C 20.

2. Просто к вашему сведению, ваша mean() функция технически возвращает среднее значение, поэтому я бы назвал ее average() вместо этого.

3. Действительно. Спасибо!

Ответ №1:

Вам нужно будет сказать mean() , на какого члена T смотреть. Для этого вы можете использовать указатель на элемент данных, например:

 template<typename Iter, typename T>
double mean(Iter begin, Iter end, double (T::*member))
{
    double s = 0;
    size_t n = 0;
    while (begin != end)
    {
        s  = (*begin  ).*member;
          n;
    }
    
    return s / n;
}

struct T
{
    double a;
    double b;
};

vector<T> v;
// fill v...
double m = mean(v.begin(), v.end(), amp;T::a/*or b*/);
 

Онлайн-Демонстрация

Вы могли бы пойти дальше, избавившись от ручного цикла и используя std::accumulate() вместо этого, например:

 #include <numeric>
 
template<typename Iter, typename T>
double mean(Iter begin, Iter end, double (T::*member))
{
    size_t n = 0;
    double s = std::accumulate(begin, end, 0.0,
        [amp;](double acc, const T amp;t){   n; return acc   t.*member; }
    );
    return s / n;
}
 

Онлайн-Демонстрация

В этом случае вы могли бы просто полностью избавиться от mean() :

 #include <numeric>

vector<T> v;
// fill v...
double m = accumulate(v.begin(), v.end(), 0.0,
    [](double acc, const T amp;t){ return acc   t.a/*or b*/; }
) / v.size();
 

Онлайн-демонстрация

Комментарии:

1. Выглядит великолепно. Большое спасибо!