Чтение онлайн

на главную - закладки

Жанры

Эффективное использование STL
Шрифт:

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

Уже лучше. Осталось каких-нибудь 745 символов, можно начинать разбираться в сообщении. В глаза бросается упоминание шаблона

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

Оказывается, практически во всех реализациях STL стандартные ассоциативные контейнеры (

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

В приведенном выше сообщении упоминается знакомый тип

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

example.срр(17):error С2440:'initalzing': 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 > >::const_iterator' 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

Сообщение стало короче, но его смысл остался туманным; нужно что-то сделать с

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

example.cpp(17):error С2440:'initalizing': cannot convert from 'class std::_Tree<НЕЧТО::const_iterator' to 'class std::_Tree<НЕЧТО:iterator'

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

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

const_iterator
в
iterator
с явным нарушением правил константности.

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

class NiftyEmailProgram {

private:

 typedef map<string, string> NicknameMap;

 NicknameMap nicknames;

public:

 void showEmailAddress(const string& nickname) const;

};

void NiftyEmailProgram::showEmailAddress(const string& nickname) const {

 NicknameMap::iterator i = nicknames.find(nickname);

 if (i != nicknames.end)…

}

Сообщение об ошибке можно истолковать лишь одним разумным образом — мы пытаемся инициализировать переменную

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

Взгляните еще раз. Да, объект

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

В этом совете были показаны некоторые текстовые подстановки, уменьшающие сложность сообщений об ошибках, но после непродолжительной практики вы сможете выполнять подстановки в голове. Я не музыкант, но мне рассказывали, что хорошие музыканты способны читать партитуру целиком, не присматриваясь к отдельным нотам. Опытные программисты STL приобретают аналогичные навыки. Они могут автоматически преобразовать конструкцию вида

std::basic_string<char, std::char_traits<char>, std::allocator<char> >
в
string
, нисколько не задумываясь над происходящим. Подобный навык разовьется и у вас, но до этих пор следует помнить, что диагностику компилятора почти всегда можно привести к вразумительному виду заменой длинных типов на базе шаблонов более короткими мнемоническими обозначениями. Во многих случаях для этого достаточно заменить расширенные определения типов именами, используемыми в программе. Именно это было сделано в приведенном примере, когда мы заменили
std::map<class string, class string, struct std::less<class string>, class std::allocator<class string> >
на
NicknameMap
.

Поделиться:
Популярные книги

Неведомые поля (сборник)

Бигл Питер Сойер
Шедевры фантастики
Фантастика:
фэнтези
6.60
рейтинг книги
Неведомые поля (сборник)

Князь Андер Арес 4

Грехов Тимофей
4. Андер Арес
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Князь Андер Арес 4

Последний Паладин. Том 5

Саваровский Роман
5. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 5

Французская новелла XX века. 1900–1939

Пруст Марсель
Проза:
классическая проза
6.25
рейтинг книги
Французская новелла XX века. 1900–1939

Шатун. Лесной гамбит

Трофимов Ерофей
2. Шатун
Фантастика:
боевая фантастика
7.43
рейтинг книги
Шатун. Лесной гамбит

Гримуар темного лорда II

Грехов Тимофей
2. Гримуар темного лорда
Фантастика:
фэнтези
попаданцы
аниме
5.25
рейтинг книги
Гримуар темного лорда II

Дважды одаренный. Том V

Тарс Элиан
5. Дважды одаренный
Фантастика:
аниме
альтернативная история
городское фэнтези
5.00
рейтинг книги
Дважды одаренный. Том V

Алекс и Алекс

Афанасьев Семен
1. Алекс и Алекс
Фантастика:
боевая фантастика
6.83
рейтинг книги
Алекс и Алекс

На границе империй. Том 5

INDIGO
5. Фортуна дама переменчивая
Фантастика:
боевая фантастика
попаданцы
7.50
рейтинг книги
На границе империй. Том 5

Геном хищника. Книга шестая

Гарцевич Евгений Александрович
6. Я - Легенда!
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Геном хищника. Книга шестая

Великий род

Сай Ярослав
3. Медорфенов
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Великий род

На цепи

Уваров
1. На цепи
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
На цепи

Страж Кодекса. Книга IV

Романов Илья Николаевич
4. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса. Книга IV

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...