Программирование >>  Включение нужных заголовков 

1 ... 58 59 60 [ 61 ] 62 63 64 ... 71


const,class string >,struct std::map<class string, class string,struct std::less<class string>, class std::allocator<class string > >:: Kfn,struct std::less<class string >, class std::allocator<class string > >::iterator

No constructor could take the source type, or constructor overload resolution was ambiguous

Уже лучше. Осталось каких-нибудь 745 символов, можно начинать разбираться в сообщении. В глаза бросается упоминание шаблона std: : Тгее. В Стандарте ничего не сказано о шаблоне с именем Tree, но мы помним, что имена, начинающиеся с символа подчеркивания и прописной буквы, зарезервированы для авторов реализаций. Перед нами один из внутренних шаблонов, используемых в реализации некой составляющей STL.

Оказывается, практически во всех реализациях STL стандартные ассоциативные контейнеры (set, multiset, map и multimap) строятся на основе базовых шаблонов. По аналогии с тем, как при использовании string в диагностике упоминается тип basicstring, при работе со стандартными ассоциативными контейнерами часто выдаются сообщения с упоминанием базовых шаблонов. В данном примере этот шаблон называется Tree, но в других известных мне реализациях встречались имена tree и rb tree, причем в последнем имени отражен факт использования красно-черных (Red-Black) деревьев, самой распространенной разновидности сбалансированных деревьев, встречающейся в реализациях STL.

В приведенном выше сообщении упоминается знакомый тип std: :map<class string.class string,struct std::less<class string>,class std::allocator<class stri ng> >. Перед нами тип используемого контейнера map, если не считать типов функции сравнения и распределителя памяти (которые не были заданы при определении контейнера). Сообщение об ошибке станет более понятным, если заменить этот тип нашим вспомогательным определением NicknameMap. Результат:

example.срр(17):еггог С2440:initializing: cannot convert from class std:: Tree<class string.struct std::pair<class string const,class string >,struct NicknameMap:: Kfn,struct std: :less<class string>,class std: :allocator<class string > >: :constJterator to class std:: Tree<class string,struct std::pair<class string const,class string >.struct NicknameMap Kfn,struct std::less<class string >, class std::allocator<class string > >::iterator

No constructor could take the source type, or constructor overload resolution was ambiguous

Сообщение стало короче, но его смысл остался туманным; нужно что-то сделать с Тгее. Известно, что шаблон Тгее зависит от реализации, поэтому узнать смысл его параметров можно только одним способом - чтением исходных текстов. Но зачем копаться в исходных текстах реализации STL, если это не нужно? Попробуем просто заменить все данные, передаваемые Tree, условным обозначением НЕЧТО и посмотрим, что из этого выйдет. Результат:

example.cpp(17):error С2440:initializing: cannot convert from class std:: Tree<HE4T0::const iterator to class std:: Тгее<НЕЧТО::iterator

No constructor could take the source type, or constructor overload resolution was ambiguous

A вот с этим уже можно работать. Компилятор жалуется на попытку преобразования const iterator в iterator с явным нарушением правил константности.



Вернемся к исходному примеру; строка, вызвавшая гнев компилятора, выделена жирным шрифтом:

class NiftyEmailProgram { private:

typedef map<string.string> NicknameMap; NicknameMap nicknames: public:

void showEmailAddress(const strings nickname) const:

void NiftyEmailProgram::showEmailAddress(const strings nickname) const {

N1cknameMap::i terator i =ni cknames.fi nd(ni cknarae);

if (i!=nicknames.end())...

Сообщение об ошибке можно истолковать лишь одним разумным образом - мы пытаемся инициализировать переменную i (типа iterator) значением типа const iterator, возвращаемым при вызове тар::find. Такая интерпретация выглядит несколько странно, поскольку find вызывается для объекта nicknames. Объект nicknames не является константным, поэтому функция find должна вернуть неконстантный итератор.

Взгляните еще раз. Да, объект nicknames объявлен как неконстантный тип тар, но функция showEmail Address является константной, а внутри константной функции все нестатические переменные класса становятся константными! Таким образом, внутри showEmailAddress объект nicknames является константным объектом тар. Сообщение об ошибке внезапно обретает смысл. Мы пытаемся сгенерировать i terator для объекта тар, который обещали не изменять. Чтобы исправить ошибку, необходимо либо привести i к типу const iterator, либо объявить showEmailAddress неконстантной функцией. Вероятно, оба способа потребуют значительно меньших усилий, чем выяснение смысла сообщения об ошибке.

В этом совете были показаны некоторые текстовые подстановки, уменьшающие сложность сообщений об ошибках, но после непродолжительной практики вы сможете выполнять подстановки в голове. Я не музыкант, но мне рассказывали, что хорошие музыканты способны читать партитуру целиком, не присматриваясь к отдельным нотам. Опытные программисты STL приобретают аналогичные навыки. Они могут автоматически преобразовать конструкцию вида std::basic string<char, std: :char traits<char>,std::al 1 ocator<char> > в string, нисколько не задумываясь над происходящим. Подобный навык разовьется и у вас, но до этих пор следует помнить, что диагностику компилятора почти всегда можно привести к вразумительному виду заменой длинных типов на базе шаблонов более короткими мнемоническими обозначениями. Во многих слзаях для этого достаточно заменить расширенные определения типов именами, используемыми в программе. Именно это было сделано в приведенном примере, когда мы заменили std: :map<class string,class string,struct std::less<class string>.class std::anocator<class string> > на NicknameMap.



Далее приведены некоторые рекомендации, которые помогут вам разобраться в сообщениях компилятора, относящихся к STL.

Для контейнеров vector и stri ng итераторы обычно представляют собой указатели, поэтому в случае ошибки с итератором в диагностике компилятора обычно указываются типы указателей. Например, если в исходном коде имеется ссылка на vector<double>:: iterator, в сообщении почти наверняка будет упоминаться указатель double*. Исключение составляет реализация STLport в отладочном режиме; в этом случае итераторы vector и string не являются указателями. За информацией о STLport и отладочном режиме обращайтесь к совету 50.

Сообщения, в которых упоминаются back insert iterator, front insert i terator и i nsert i terator, почти всегда означают, что ошибка была допущена при вызове back inserter, front inserter или inserter соответственно (back i nserter возвращает объект типа back insert i terator, front i nserter возвращает объект типа frontinserti terator, a inserter возвращает объект типа i nsert i terator; за информацией об этих типах обращайтесь к совету 30). Если эти функции не вызывались в программе, значит, они были вызваны из других функций (косвенно или явно).

Сообщения с упоминаниями binderlst и binder2nd обычно свидетельствуют об ошибке при использовании bindlst и bindZnd (bindlst возвращает объект типа binderlst, а bindZnd возвращает объект типа binder2nd).

Итераторы вывода (например, ostreain iterator и ostreambuf iterator - см. совет 29, а также итераторы, возвращаемые back i nserter, fronti nserter и inserter) выполняют свои операции вывода или вставки внутри операторов присваивания, поэтому ошибки, относящиеся к этим типам итераторов, обычно приводят к появлению сообщений об ошибке внутри операторов присваивания, о которых вы и понятия не имеете. Чтобы понять, о чем идет речь, попробуйте откомпилировать следующий фрагмент:

vector<string*> v: Попытка вывода содержимого

copy(v.begin().V.endO. контейнера указателей string*

ostream iterator<string>(cout. \n )); как объектов string

Если полученное сообщение об ошибке исходит из реализации алгоритма STL (то есть если код, в котором произошла ошибка, находится в <al gorithin>), вероятно, проблема связана с типами, которые вы пытаетесь передать этому алгоритму. Пример - передача итераторов неправильной категории. Попробуйте откомпилировать следующий фрагмент:

list<int>::iterator il.i2; Передача двусторонних итераторов sort(il.i2); алгоритму, которому необходимы итераторы

произвольного доступа

Если вы используете стандартный компонент STL (например, контейнер vector или string, алгоритм for each), а компилятор утверждает, что он понятия не имеет, что имеется в виду, скорее всего, вы забыли включить необходимый заголовочный файл директивой #1 ncl ude. Как объясняется в совете 48, эта проблема может нарушить работоспособность кода, успешно компилировавшегося в течение некоторого времени, при переносе его на другую платформу.



1 ... 58 59 60 [ 61 ] 62 63 64 ... 71

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика