Размер неизвестного контейнера

Я всегда читал, что использование этого кода не так хорошо:

std::vector<T> my_vector;
...
std::sort(my_vector.begin(), my_vector.end());

Лучше написать его как:

std::vector<T> my_vector;
...
std::sort(std::begin(my_vector), std::end(my_vector));

Поскольку std:: begin будет работать со всеми контейнерами, включая обычные массивы.

Какова альтернатива my_vector.size(), которая будет работать для всех контейнеров, включая обычные массивы?

Ответы

Ответ 1

Фактически использование std::begin(my_vector) - это не правильная вещь! Если вы хотите выбрать пункт настройки, вы предпочитаете использовать

using std::begin;
using std::end;
std::sort(begin(cont), end(cont));

Этот подход пытается найти begin(cont) с помощью ADL и, если не удается найти подходящую версию, откажитесь от использования std::begin.

К сожалению, нет значения std::size для точки настройки, например std::begin. Было бы неплохо использовать std::distance():

std::distance(begin(cont), end(cont));

Однако для типичных контейнеров на основе node или, в более общем плане, для итераторов неслучайного доступа этот подход будет перемещаться по элементам, а затем получать размер от сохраненного значения. Таким образом, я думаю, вы бы хотели называть cont.size(). Было бы относительно просто определить подходящую точку настройки:

namespace util {
    template <typename C>
    typename C::difference_type size(C const& c) {
        return c.size();
    }
    template <typename T, std::size_t N>
    std::size_t size(T const(&)[N]) {
        return N;
    }
}

Как отмечалось в комментариях, в рабочий документ для С++ 17 была добавлена ​​функция non-member size() (см. нижняя часть синопсиса в 24.3 [итератор.синопоз]). N4280 - это документ, в котором предлагается изменение. В этой статье также предлагаются функции empty() и data(), которые также были добавлены. Все эти функции объявлены в <iterator>.

Версия, добавленная в С++ 17, использует decltype() в элементе size() непосредственно в возвращаемом типе. Кроме того, он объявляет функцию constexpr:

template <typename C>
constexpr auto size(C const& c) -> decltype(c.size()) {
    return c.size();
}