2013-10-08 2 views
10

Учитывая встроенный массив x произвольного типа T, есть функции std::begin() и std::end(), которые я могу назвать, но почему нет std::size()? Кажется странным не иметь этого.Есть ли какая-то функция типа std :: size()?

Я мог бы использовать std::end(x)-std::begin(x), но все равно std::size(x) было бы лучше.

Да, я знаю классы std::vector и std::array. Это просто вопрос о том, почему в STL нет ничего такого простого.

+0

Существует std :: distance, похоже на то, что вы ищете – aaronman

+0

Должен ли 'std :: size' работать только для типа, если он дешевый или он должен работать независимо? – Yakk

+0

@Yakk Хороший вопрос. Наверное, независимо. Я считаю, что все типы контейнеров имеют функцию size()? – Adrian

ответ

14

Там в std::extent, который должен быть применен к типа массива:

#include <type_traits> 

int a[12]; 

assert(std::extent<decltype(a)>::value == 12); 

В качестве альтернативы вы можете использовать std::distance(std::begin(a), std::end(a)).

Первое явно является постоянным выражением, хотя на практике последнее также может быть составлено статически.

Наконец, всегда есть доморощенные решение:

template <typename T, std::size_t N> 
constexpr std::size_t array_size(T const (&)[N]) 
{ return N; }; 
+2

Да, я знаю о домашней версии. Мне просто интересно, почему это не было в STL. Спасибо за метод 'std :: extent'. – Adrian

+0

@Adrian: Я полагаю, что для этого нет такого общего использования ... в большинстве случаев вам нужен размер, вы хотите перебирать массив, что вы можете сделать другими способами. Но, возможно, это будет добавлено в какой-то момент. –

+1

'std :: size()' было бы полезно, если бы хотелось объявить несколько массивов той же длины, в которых длина первого была определена посредством инициализации списка. –

2

Алгоритм STL работает на итераторах, а не на любом контейнере, размер контейнера STL требует начала и конца, что не имеет смысла. Для таких мы уже имеем std::distance

+0

Можно выполнить: 'int x [] = {1,2,3,4,5}; for_each (std :: begin (x), std :: end (x), [] (int элемент) {std :: cout << element << std :: endl;}); 'который показывает, что он может использовать алгоритмы STL. – Adrian

+1

@Adrian: Почему бы не' for (int element: x) std :: cout << element << std :: endl; '? –

+0

@Adrian Извините, я не понял контекст, что может использовать алгоритм STL? – P0W

0

Я полагаю, вы имеете в виду C-подобные массивы. Ответ, как сказал Бьярне Страуструп, заключается в том, что «массив в C - это тип данных, который настолько глуп, что даже не знал, сколько элементов он получил». Как только массив распадается на указатель, нет способа узнать, сколько элементов там, где находится «массив».

+0

Где это сказал Бьярне Страуструп? Быстрый поиск не вызывает эту цитату нигде. Мне кажется, мне кажется, что информация остается доступной до тех пор, пока вы работаете с типом массива. Только после прекращения работы с типом массива информация теряется. – hvd

+1

Bjarne Stroustrup - Сущность C++: с примерами в C++ 84, C++ 98, C++ 11 и C++ 14 на GoingNative 2013 http://channel9.msdn.com/Events/GoingNative/2013/Открытие-Keynote-Bjarne-Stroustrup в 49:19. –

+0

Спасибо. Неудивительно, что поиск не принес этого, если он не был расшифрован. :) Это все еще кажется фиктивным для меня. – hvd

20

Просто к сведению, чтобы люди знали, что N4280 «размер, не являющиеся членами() и более (Revision 2)» был принят в C++ 17 Рабочий проект. Это включает std::size(), а также std::empty() и std::data().

+0

Отлично. Вы знаете, почему 'template constexpr bool empty (const T (& array) [N]) noexcept;' возвращает только 'false'? «N» может быть нулевым. – user2023370

+0

@ user2023370, 'int ar [0];' не будет компилироваться. – Ajay

+0

@Ajay как насчет 'int ar [] = {};'? –

Смежные вопросы