2016-01-24 6 views
9

Я заметил, что контейнеры std:: имеют public, псевдонимы в классе (typedef/using). Например, см. Типы членов в http://en.cppreference.com/w/cpp/container/vector.Являются ли общедоступными, в классе typedefs необходимые в C++ 1y?

Как они полезны? Разве это не реликвия времен, когда у C++ не было таких вещей, как auto и decltype?

При реализации пользовательского контейнера, должен ли он иметь такие typedef s? Что я потеряю, если не смогу их предоставить?

+2

Просьба указать конкретный * пример *, где «вещи, такие как' auto' и 'decltype'» выполняют эту работу, и где ранее публичный 'typedef' должен был использоваться. –

+0

Я думаю, что эти типы существуют, так что различные типы признаков, используемые алгоритмами в заголовке алгоритма, не будут явно создаваться для каждого типа контейнера. – StoryTeller

+0

Он также помогает читабельности и ремонтопригодности. –

ответ

7

Если вам нужен контейнер, совместимый с стандартной библиотекой, вам нужно предоставить typedefs.

Если вы посмотрите на документацию, например, в cppreference, вы увидите отрывки, как это:

станд :: вектор отвечает требованиям контейнер, AllocatorAwareContainer, SequenceContainer, ContiguousContainer (для T, кроме BOOL) (с C++ 17) и ReversibleContainer.

Если вы посмотрите контейнер или SequenceContainer или любую другую вещь, перечисленную здесь, вы найдете список требований, и определение типов (или, вернее, типов, они не имеют быть определением типов, хотя они часто являются) среди них.

Итак, если вы строите контейнер в стандартном смысле этого слова, вам необходимо предоставить typedefs (и, конечно же, удовлетворять всем остальным требованиям).

C++ 11 может теоретически ослабить требования, но этого не произошло. Может быть, потому, что

std::vector<int>::iterator 

чертовски много более читаемым, чем

decltype(std::declval<std::vector<int>>().begin()) 

Или, возможно, по какой-то другой причине.

+0

Я думаю, что вопрос скорее о том, «они служат полезной цели», а не «есть ли формальное требование иметь их». Но да в конце вопрос * также * о формальных требованиях. –

+0

@ Cheersandhth.-Alf Это, но это тоже помогает. Спасибо, н.м. , – PSkocik

+0

Приобретено для наблюдения читаемости, но обратите внимание, что это всего лишь вопрос определения * правильных абстракций поддержки *. В C++ 03 абстракциями поддержки были простые определения typedef или типов. В C++ 11 для нового кода они обычно не должны быть: например. типы могут быть выведены по признакам. –

4

Они чрезвычайно полезны при работе с метапрограммированием, периодом.

давайте поймать контейнер по ссылке один раз, если это контейнер POD, и в другой раз, когда это не так:

template <class T> 
typename std::enable_if_t<std::is_pod<typename T::value_type>::value> 
doSomething(T& container){ 
    //do something 
} 

template <class T> 
typename std::enable_if_t<!std::is_pod<typename T::value_type>::value> 
doSomething(T& container){ 
    //do something 
} 

Я делаю много C++ для Windows, а с Windows API обеспечивают C структур , Я использую многие методы, подобные этим, чтобы отличить реальные объекты C++ от структур WinApi.

1

typedef (ы) позволяют отделять реализации от интерфейсов.

Взять на себя внимание, что на раннем этапе C++ не определяет auto, как он определен сейчас, и decltype отсутствовал в стандарте.

Но даже сейчас, когда у вас есть auto и decltype, иногда лучше указать тип объекта. В противном случае код может быть трудно читаемым или может привести к ошибкам.

Рассмотрим простой пример с спецификатор типа auto

unsigned int x = 0; 
long y = 0; 

auto p = new auto(x + y); 

Можете ли вы сказать, что тип указателя р?

Является ли выражение *p неподписанного типа или подписи?

Ответ зависит от используемой платформы. Тип p может быть либо long *, либо unsigned long *.

Аналогичная проблема существует для стандартных контейнеров. Таким образом, Стандарт вводит имена общего типа, такие как size_type, который гарантирует, что этот тип является неподписанным, но его ширина может варьироваться в зависимости от платформы.

Также это позволяет писать общий код.

В моем профиле есть ссылка на мою статью, где показана проблема, связанная с тем, что стандартный класс std::bitset не имеет общего типа size_type. В этом случае, если вам нужно заменить пример класса std::vector<bool> на std::bitset, вам необходимо изменить код везде, где было использовано либо size_type, либо явный тип, например size_t.

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