С++. Параметры шаблонов функций.

Эта статья является логическим продолжением статьи Шаблоны функций в С++ для начинающих Первое знакомство. В той статье был использован пример кода программы, где шаблонная функция выбирает большее из двух чисел число:

И особенностью этого примера было проведение компилятором С++ неявного преобразования: вместо ожидаемого 66.999 у нас получается 66
В той статье объяснялось, почему. Так вот, иногда это может быть нормально, но из-за того, что мы получаем не то, что ждём, можно говорить об ошибке.

На заметку:

  • Смешивание разных типов в вычислении может приводить к логическим ошибкам.

Эти логические ошибки возникают в основном из-за незнаний правил неявных преобразований типов в языке С++. Если человек понимает как происходят приведения типов, то он поймёт, где можно смешать типы, а где смешивать не нужно, но если человек не понимает правил неявных преобразований типов, то смешение им типов в одном вычислении с большой вероятностью ни к чему хорошему не приведёт.
Скорее всего человек, написавший показанный код, хотел увидеть именно 66.999, а не усечённое до целого число 66. Будет ли отдано число с типом int или double в нашем примере напрямую — зависит от порядка отдаваемых в функцию аргументов:



И вот вопрос: "Как используя шаблонную функцию выводить именно то, что логичнее всего ожидать?". Как не зависеть от порядка передаваемых в функцию аргументов?
На заметку:

  • Параметры шаблонов очень похожи на параметры функций, но в отличие от параметров функций, параметры шаблонов умеют автоматически выводить типы. Иногда имеет смысл помочь автоматике и вручную подсказать правильный тип нужному аргументу. Для этого используются угловые скобки в месте обращения к шаблонной функции, а в угловых скобках пишутся типы, которые будут отдаваться в шаблон. Типы, описываемые в угловых скобках, предназначенные для шаблонных параметров, я буду называть шаблонными аргументами. Шаблонные аргументы уходят в шаблон и параметры, заявленные в шаблоне, поочереди, слева-направо, впитывают в себя эти аргументы.
Например, в показанном примере нас мало устраивает наглость компилятора и вывод на экран значения с усечённым до целого типом. Мы можем вручную подсказать, что мы ожидаем именно double. Для этого нужно использовать шаблонные аргументы.

Теперь всё работает как и должно, double не усекается и на экран выводится число в своём нормальном виде.
Смысл на самом деле очень простой. Всё как в функциях, только если у функций параметры обозначают значения, параметры шаблонов обозначают типы, и аргументы шаблонов можно опускать, если сильно надеяться на автоматический вывод типов, но можно и задавать вручную, подсказывая компилятору действительно нужный тип.
Есть ещё один вариант выхода из сложившейся ситуации с неправильным для нас выводом на экран числа. Если полностью довериться автоматическому выводу типов, то можно использовать не два, а три параметра шаблона: один параметр шаблона непосредственно для типа функции, второй параметр шаблона для одного типа параметра функции и третий параметр для другого типа параметра функции.

Параметры шаблона поочереди принимают отданные в шаблон аргументы, слева-направо: в T1 приходит int, в T2 приходит double, в T3double. Поскольку функция отдаёт значение с типом T3, а в T3 пришёл тип double, нам и отдаётся значение с типом double, как мы и хотели.
На заметку:

  • Если все типы, заявленные в шаблоне, могут быть выведены из типов приходящих в параметры функции аргументов, тогда шаблонные аргументы, в момент обращения к шаблонной фунции, можно или опускать полностью, или опускать частично, в противном случае будет необходимо явно указать все типы в аргументах шаблону.
В нашем последнем примере два из трёх типов легко выводятся из значений, отданных вовнутрь функции, но третий тип выводить неоткуда, из-за этого пришлось явно указать все типы. Хотя, если бы были типы, которые могли бы вывестись из значений отданных функции, и они бы были написаны после "смущающего шаблон типа", то вполне достаточным вариантом могло бы быть описание всех типов до последнего "смущающего типа", т. е. немогущего ни из чего вывестись типа.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/kollektiv-avtorov/zadachi-po-programmirovaniu-11252207/?lfrom=15589587

Последние комментарии

Яндекс.Метрика