Все ли контейнеры имеют функцию .size ()?

Для домашнего задания я должен создать шаблонную функцию стандартного отклонения, которая может быть выполнена в любом контейнере. Вот что у меня есть:

template <typename Container>
double findMean(Container c, int count){
double sum = 0;
for (auto&& e : c){
sum += e;
}
sum /= count;
return sum;
}

template <typename Container>
double findStDev(Container c){
double mean = findMean(c, c.size());
std::cout << mean << std::endl;
for (auto&& e : c){
e -= mean;
e *= e;
}
mean = sqrt(findMean(c, c.size()));
return mean;
}

В первый раз я нахожу среднее значение, которое хочу разделить на полный размер контейнера (n), но когда я нахожу его во второй раз для стандартного отклонения, мне нужно разделить на размер-1 (n-1).

Доступна ли функция .size () для всех контейнеров c ++?

-1

Решение

Почти. Согласно таблице 96 — требования к контейнерам в N3797, все контейнеры в стандартной библиотеке должны обеспечивать функцию-член size, Он должен иметь постоянное время выполнения и возвращать значение distance(a.begin(),a.end()) для контейнера a,

Однако, есть одно (и только одно) исключение, упомянутое позже:

Forward_list удовлетворяет всем требованиям контейнера (таблица 96), за исключением того, что член size ()
функция не предусмотрена.

(N3797 23.3.4.1, пункт 2)

Это означает, что std::forward_list действительно стандартный контейнер, который делает не иметь функцию-член size,

6

Другие решения

В старой доброй традиции STL ваш шаблон может принимать пару прямых итераторов и подсчитывать расстояние при суммировании элементов.

#include <cstddef>
#include <iterator>

template<typename FwdIter,
typename value_type = typename std::iterator_traits<FwdIter>::value_type>
value_type
mean(const FwdIter begin, const FwdIter end)
{
std::size_t count {0};
value_type sum {};
for (auto it = begin; it != end; ++it)
{
sum += *it;
++count;
}
return sum / count;
}

Это будет работать для стандартных библиотечных контейнеров, массивов, указателей, что угодно. Для контейнеров вы можете просто определить удобный шаблон переадресации, который вызывает cbegin а также cend если ты хочешь.

Обратите внимание, что я исключил любые ограничения типов из приведенного выше примера. На практике, вы должны, вероятно, std::enable_if шаблон только при особых условиях, таких как, если std::is_arithmetic<value_type>,

2

Все ли контейнеры имеют функцию .size ()?

Нет. Большинство из них делают, и до C ++ 11, все они сделали. Однако в C ++ 11 появился шаблон класса односвязных списков. std::forward_list, который не иметь size() функция-член. Все остальные контейнеры делают, и текущий стандарт определяет, что алгоритмическая сложность равна O (1). Pre-C ++ 11, std::list было разрешено иметь линейную сложность.

2
По вопросам рекламы [email protected]