В этом совете были показаны некоторые текстовые подстановки, уменьшающие сложность сообщений об ошибках, но после непродолжительной практики вы сможете выполнять подстановки в голове. Я не музыкант, но мне рассказывали, что хорошие музыканты способны читать партитуру целиком, не присматриваясь к отдельным нотам. Опытные программисты STL приобретают аналогичные навыки. Они могут автоматически преобразовать конструкцию вида std::basic_string
в string
, нисколько не задумываясь над происходящим. Подобный навык разовьется и у вас, но до этих пор следует помнить, что диагностику компилятора почти всегда можно привести к вразумительному виду заменой длинных типов на базе шаблонов более короткими мнемоническими обозначениями. Во многих случаях для этого достаточно заменить расширенные определения типов именами, используемыми в программе. Именно это было сделано в приведенном примере, когда мы заменили std::map
на NicknameMap
.
Далее приведены некоторые рекомендации, которые помогут вам разобраться в сообщениях компилятора, относящихся к STL.
• Для контейнеров vector
и string
итераторы обычно представляют собой указатели, поэтому в случае ошибки с итератором в диагностике компилятора обычно указываются типы указателей. Например, если в исходном коде имеется ссылка на vector
, в сообщении почти наверняка будет упоминаться указатель double*
. Исключение составляет реализация STLport в отладочном режиме; в этом случае итераторы vector
и string
не являются указателями. За информацией о STLport и отладочном режиме обращайтесь к совету 50.
• Сообщения, в которых упоминаются back_insert_iterator
, front_insert_iterator
и insert_iterator
, почти всегда означают, что ошибка была допущена при вызове back_inserter
, front_inserter
или inserter
соответственно (back_inserter
возвращает объект типа back_insert_iterator
, front_inserter
возвращает объект типа front_insert_iterator
, a inserter
возвращает объект типа insert_iterator
; за информацией об этих типах обращайтесь к совету 30). Если эти функции не вызывались в программе, значит, они были вызваны из других функций (косвенно или явно).
• Сообщения с упоминаниями binder1st
и binder2nd
обычно свидетельствуют об ошибке при использовании bind1st
и bind2nd
(bind1st
возвращает объект типа binder1st
, a bind2nd
возвращает объект типа binder2nd
).
• Итераторы вывода (например, ostream_iterator
и ostream_buf_iterator
— см. совет 29, а также итераторы, возвращаемые back_inserter
, front_inserter
и inserter
) выполняют свои операции вывода или вставки внутри операторов присваивания, поэтому ошибки, относящиеся к этим типам итераторов, обычно приводят к появлению сообщений об ошибке внутри операторов присваивания, о которых вы и понятия не имеете. Чтобы понять, о чем идет речь, попробуйте откомпилировать следующий фрагмент:
vector
copy(v.begin, v.end, // контейнера указателей string*
ostream_iterator
• Если полученное сообщение об ошибке исходит из реализации алгоритма STL (то есть если код, в котором произошла ошибка, находится в
), вероятно, проблема связана с типами, которые вы пытаетесь передать этому алгоритму. Пример — передача итераторов неправильной категории. Попробуйте откомпилировать следующий фрагмент:
list
sort(i1, i2); // алгоритму, которому необходимы итераторы
// произвольного доступа
• Если вы используете стандартный компонент STL (например, контейнер vector
или string
, алгоритм for_each
), а компилятор утверждает, что он понятия не имеет, что имеется в виду, скорее всего, вы забыли включить необходимый заголовочный файл директивой #include
. Как объясняется в совете 48, эта проблема может нарушить работоспособность кода, успешно компилировавшегося в течение некоторого времени, при переносе его на другую платформу.
Совет 50. Помните о web-сайтах, посвященных STL