Читаем Язык программирования C++. Пятое издание полностью

Проблема в том, что, глядя на тип параметра функции func(), невозможно определить уникальный тип для аргумента шаблона. Вызов функции func() мог бы создать экземпляр версии функции compare(), получающей целые числа или версию, получающую строки. Поскольку невозможно идентифицировать уникальный экземпляр для аргумента функции func(), этот вызов не будет откомпилирован.

Неоднозначность вызова функции func() можно устранить при помощи явных аргументов шаблона:

// ok: явно определенная версия экземпляра compare()

func(compare); // передача compare(const int&, const int&)

Это выражение вызывает версию функции func(), получающую указатель на функцию с двумя параметрами типа const int&.

Когда возвращается адрес экземпляра шаблона функции, контекст должен позволять однозначно идентифицировать тип или значение для каждого параметра шаблона.

<p><image l:href="#books.png"/>16.2.5. Дедукция аргумента шаблона и ссылки</p></span><span>

Чтобы лучше понять дедукцию типа, рассмотрим такой вызов функции где параметр функции p является ссылкой на параметр типа шаблона T:

template void f(Т &p);

Обратите внимание на два момента: здесь применяются обычные правила привязки ссылок; и спецификаторы const здесь нижнего уровня, а не верхнего.

Дедукция типа из параметров ссылки на l-значения функций

Когда параметр функции представляет собой обычную ссылку (l-значение) на параметр типа шаблона (т.е. имеющего форму T&), правила привязки гласят, что передавать можно только l-значения (например, переменная или выражение, возвращающее ссылочный тип). Этот аргумент может быть или не быть константным. Если аргумент будет константой, то тип Т будет выведен как константный:

template void f1(Т&); // аргумент должен быть l-значением

// вызовы f1() используют ссылочный тип аргумента как тип параметра

// шаблона

f1(i);  // i - это int; параметр шаблона Т - это int

f1(ci); // ci - это const int; параметр шаблона Т - это const int

f1(5);  // ошибка: аргумент ссылочного параметра

        // должен быть l-значением

Если параметр функции имеет тип const Т&, обычные правила привязки гласят, что можно передать любой вид аргумента — объект (константный или нет), временный объект или литеральное значение. Когда сам параметр функции является константой, выведенный для параметра Т тип не будет константным типом. Константность является частью типа параметра функции, и поэтому она не становится также частью типа параметра шаблона:

template void f2(const T&); // может получать r-значения

// параметр в f2() - это const &; const в аргументе неуместен

// в каждом из этих трех вызовов параметр функции f2() выводится

// как const int&

f2(i);  // i - это int; параметр шаблона Т - это int

f2(ci); // ci - это const int, но параметр шаблона T - это int

f2(5);  // параметр const & может быть привязан к r-значению;

        // Т - это int

Дедукция типа из параметров ссылки на r-значения функций

Когда параметр функции является ссылкой на r-значение (см. раздел 13.6.1), т.е. имеет форму Т&&, обычные правила привязки гласят, что этому параметру можно передать r-значение. При этом дедукция типа ведет себя таким же образом, как дедукция обычного ссылочного параметра функции на l-значение. Выведенный тип для параметра Т — это тип r-значения:

template void f3(T&&);

f3(42); // аргумент - это r-значение типа int; параметр

        // шаблона Т - это int

Сворачивание ссылок и параметры ссылок на r-значения

Предположим, что i является объектом типа int. Можно подумать, что такой вызов, как f3(i), будет недопустим. В конце концов, i — это l-значение, а ссылку на r-значение обычно нельзя связать с l-значением. Однако язык определяет два исключения из обычных правил привязки, которые позволяют это. На этих исключениях из правил основан принцип работы таких библиотечных функций, как move().

Перейти на страницу:

Похожие книги

Adobe Flash. Создание аркад, головоломок и других игр с помощью ActionScript
Adobe Flash. Создание аркад, головоломок и других игр с помощью ActionScript

Данная книга посвящена программированию игр с помощью ActionScript. Здесь вы найдете подробные указания, необходимые для создания самых разных игр – аркад, головоломок, загадок и даже игровых автоматов. В тексте приведены исходные коды программ и детальные, доступно изложенные инструкции. Базовые принципы программирования ActionScript рассматриваются на примере игр, однако вы без труда сможете применить полученные знания и для разработки неигровых проектов, таких как Web-дизайн и реклама. Рекомендации Гэри Розенцвейга помогут вам не только придумывать занимательные игры и размещать их на Web-сайте, но и оптимизировать скорость их работы, а также защищать свои творения от несанкционированного копирования. Представленный в книге код несложно изменить для использования в других программах.Книга предназначена для широкого круга читателей – создателей анимационных роликов, художников-оформителей, программистов и разработчиков Web-сайтов. Издание может также выступать в качестве практического пособия по изучению ActionScript.

Гэри Розенцвейг

Программирование, программы, базы данных / Программирование / Книги по IT
Секреты приложений Google
Секреты приложений Google

Даже продвинутые пользователи Интернета не подозревают о тех огромных возможностях, которые предоставляют сервисы Google. Автор рассказывает о таких «секретах» сервисов, которые просто немедленно хочется использовать! Создавать сайты и презентации, бродить по улочкам Парижа, изучать звездное небо – все это доступно каждому, кто сидит у экрана монитора и имеет доступ в Интернет. Книга научит вас работать с веб-приложениями и тысячекратно увеличить свои возможности с помощью новейших технологий. Она написана легким, доступным языком и не требует от читателя наличия каких-либо специальных знаний. Книга содержит множество примеров, иллюстраций и будет полезна всем, кто не стоит на месте и стремится сделать свою жизнь более насыщенной и интересной.

Денис Балуев , Денис Игоревич Балуев

Программирование, программы, базы данных / Интернет / Программное обеспечение / Книги по IT