Какая связь между шаблоном C ++ и утиным набором текста?

Для меня в шаблоне C ++ использовалась идея «утиной печати», верно? Означает ли это, что все общие типы, указанные в классе или методе шаблона, относятся к типу утки?


person Thomson    schedule 03.08.2011    source источник


Ответы (7)


Для меня в шаблоне C ++ использовалась идея «утиной печати», верно?

Нет, шаблоны C ++ используются для реализации универсального кода. То есть, если у вас есть код, который может работать с более чем одним типом, вам не нужно дублировать его для каждого типа. Такие вещи, как std::vector и std::list - очевидные примеры этого в действии. Шаблоны C ++ использовались для выполнения других задач, но изначальной целью была универсальность.

Означает ли это, что все общие типы, указанные в классе или методе шаблона, относятся к типу утки?

Нет, это просто «нормальные» типы, как и любой другой тип в C ++. Они просто не известны, пока шаблон не будет фактически создан.

Однако шаблоны можно использовать для реализации чего-то вроде утиного набора текста. Итераторы являются примером. Рассмотрим эту функцию:

template<class InputIterator, class OutputIterator>
    OutputIterator copy(InputIterator first, InputIterator last,
                        OutputIterator result)
{
    while (first!=last) *result++ = *first++;
    return result;
}

Обратите внимание, что функция copy может принимать аргументы любого типа, а также реализует оператор неравенства, оператор разыменования и оператор постфиксного приращения. Это, вероятно, так близко к утиной печати, как вы получите в C ++.

person In silico    schedule 03.08.2011
comment
Исходя из моего ограниченного понимания утиной печати, ваше описание функции копирования звучит так, как если бы она использовала утиную типизацию. Что именно характеризует утиную типизацию, которую не выполняют шаблоны C ++? - person aioobe; 03.08.2011
comment
@aioobe: Насколько я понимаю, утиная типизация - это то, что происходит во время выполнения, а не во время компиляции. Я говорю, что это похоже на утиную типизацию, потому что компилятор по-прежнему выполняет проверку типов во время компиляции, как будто он не выполняет утиную типизацию. Просто типы не известны до тех пор, пока вы не воспользуетесь шаблоном. - person In silico; 03.08.2011
comment
С точки зрения создания экземпляров шаблона, различие времени компиляции и времени выполнения соответствует пре-созданию и пост-созданию экземпляра. ИМХО, различие времени компиляции / времени выполнения, возможно, лучше рассматривать как пример различия «время компиляции / время после компиляции» (т.е. «поведение известно / определено во время или до времени компиляции» против «после») . Где, например. python проверяет при вызове object.hello (), а не при компиляции в байт-код, C ++ проверяет при попытке скомпилировать Type1 & object :: hello (Type1 x, Type2 y) {return x + y; }, а не при повороте c = object.hello (a, b); в это. - person John Allsup; 18.07.2017
comment
Хотя ваша позиция соответствует тому, что кажется общепринятым пониманием того, что утиная типизация подразумевает проверки во время выполнения, существует некоторая обоснованная критика этого определения самого термина, из-за которого категорическое "нет" в начале вашего ответ довольно предвзятый. Конец вашего ответа пытается исправить это предубеждение. ИМХО, вам с самого начала следовало ответить более подробно. - person Johan Boulé; 19.08.2017

Для меня шаблоны C ++ - это версия утиной печати во время компиляции. Компилятор будет компилировать, например, Class, и пока ваш Duck имеет все необходимые типы, он будет создавать экземпляр класса.

Если что-то не так (например, отсутствует конструктор копирования), компиляция не выполняется. Аналогом в реальном ducktyping является сбой, когда вы вызываете функцию с типом, отличным от ducktyping. И вот это произойдет во время выполнения.

person tgmath    schedule 03.08.2011
comment
хмм .. мое понимание из утиного набора текста состоит в том, что вы пытаетесь узнать тип. Это означает, что вы сталкиваетесь с динамическим объектом и не уверены в его типе. В шаблонах C ++ вы должны быть уверены в типе, чтобы создать его экземпляр. - person duedl0r; 03.08.2011
comment
-1. Утиная типизация не обязательно подразумевает динамическую типизацию или проверки во время выполнения. Утиная типизация во время компиляции по-прежнему утиная типизация. - person JSBձոգչ; 03.08.2011
comment
Шаблоны C ++ изначально были основаны на воспроизведении токенов. Это все еще проявляется в его свойствах типа утки. - person Marco van de Voort; 01.09.2011

Утиная печать означает: «Если она крякает, как утка, и ходит как утка, значит, это утка». В информатике нет формального определения, с которым мы могли бы сравнивать C ++.

Конечно, C ++ не идентичен (например) Python, но оба они имеют концепцию неявно определенных интерфейсов. Интерфейс, требуемый для объекта, используемого в качестве аргумента функции Python, - это то, что функция с ним делает. Интерфейс, требуемый для типа, используемого в качестве аргумента шаблона C ++, соответствует тому, что шаблон делает с объектами этого типа. В этом сходство, и это основание, по которому следует оценивать шаблоны C ++.

Кроме того, из-за вывода аргументов шаблона в C ++ вы можете попытаться передать любой старый объект, и компилятор выяснит, может ли он создать экземпляр шаблона функции.

Одно отличие состоит в том, что в C ++, если аргумент не крякает, компилятор возражает. В Python только объекты времени выполнения (и только если функция действительно вызывается, если в коде есть условные выражения). Это различие в природе интерфейса, требуемого от объекта / типа - в C ++ либо шаблон требует, чтобы конкретное выражение было действительным, либо этого не требует. В Python необходимые допустимые выражения могут зависеть от значений времени выполнения ранее необходимых выражений. Итак, в Python вы можете попросить объект, который либо громко, либо тихо крякает, а если он громко крякает, ему тоже нужно ходить. В C ++ вы можете сделать это с помощью условного dynamic_cast, и если объем является константой времени компиляции, вы можете сделать это со специализацией шаблона, но вы не можете использовать статическую типизацию, чтобы сказать, что утке нужно ходить только в том случае, если quack_volume() возвращает loud. И, конечно же, в Python требуемый интерфейс может быть не совсем «обязательным» - поведение, если метод отсутствует, вызывает исключение, и можно было бы задокументировать и гарантировать поведение вызывающего, если это произойдет.

Вам решать, определяете ли вы «утиную печать», чтобы это различие означало, что в C ++ ее нет.

person Steve Jessop    schedule 03.08.2011

Не совсем. Утиные типы (стиль динамического типа) никогда не вызовут ошибок типа во время компиляции, потому что они просто не имеют никакого типа. С шаблонами у вас не будет типов, пока вы не создадите экземпляр шаблона. Как только вы это сделаете, переменные будут иметь разные типы, и вы действительно получите ошибки времени компиляции.

Кроме того, с типами утки у вас может быть одна переменная, указывающая на разные типы объектов, потому что переменные просто не имеют типов. Это невозможно с шаблонами - после их создания переменные имеют один определенный тип.

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

person eran    schedule 03.08.2011

Да, вроде - например, если тип X имеет методы AddRef(), Release() и QueryInterface() с соответствующими сигнатурами, его можно использовать как объект COM с классом шаблона CComPtr. Но это не полная утиная типизация - для параметров по-прежнему применяется проверка типов.

person sharptooth    schedule 03.08.2011

Нет, это другое понятие. duck typing - это метод определения типа контейнера с динамической типизацией. Шаблоны C ++ не являются динамически типизированными, они создаются с конкретным типом.

person duedl0r    schedule 03.08.2011

Википедия охватывает это различие.

person Mechanical snail    schedule 03.08.2011