|
Программирование >> Инициализация объектов класса, структура
определение шаблона функции e> Type ) { /* ... */ } template <class Type> Type min( Type, Typ / / явная специазация для Type == double template<> double min<double>( double, double ); void manip( int ii, double dd ) { ошибка: вывод аргументов шаблона неудачен, нет функций-кандидатов для данного вызова min( dd, ii ); Шаблон функции min() специализирован для аргумента double. Однако эта специализация не попадает в множество функций-кандидатов. Процесс вывода для вызова min() завершился неудачно, поскольку аргументы шаблона, выведенные для Type на основе разных фактических аргументов функции, оказались различными: для первого аргумента выводится тип double, а для второго - int. Поскольку вывести аргументы не удалось, в множество кандидатов никакая функция не добавляется, и специализация min(double, double) игнорируется. Так как других функций-кандидатов нет, вызов считается ошибочным. Как отмечалось в разделе 10.6, тип возвращаемого значения и список формальных параметров обычной функции может точно соответствовать аналогичным атрибутам функции, конкретизированной из шаблона. В следующем примере min(int,int) - это обычная функция, а не специализация шаблона min() , поскольку, как вы, вероятно, объявление шаблона функции template <class T> T min( T, T ); обгчная функция min(int,int) помните, объявление специализации должно начинаться с template<>: int min( int, int ) { } Вызов может точно соответствовать как обычной функции, так и функции, конкретизированной из шаблона. В следующем примере оба аргумента в miin(ai[0],99) имеют тип int. Для этого вызова есть две устоявших функции: обычная min(int,int) и конкретизированная из шаблона функция с тем же типом возвращаемого значения и int ai[4] = { 22, 33, 44, 55 }; int main() { вызывается обычная функция min( int, int ) min( ai[0], 99 ); списком параметров: Однако такой вызов не является неоднозначным. Обычной функции, если она существует, всегда отдается предпочтение, поскольку она реализована явно, так что перегрузка разрешается в пользу обычной функции min(int,int) . шаблон функции template <class T> T min( T, T ) { ... } это обгчная функция, не определенная в программе int min( int, int ); int ai[4] = { 22, 33, 44, 55 }; int main() { ошибка сборки: min( int, int ) не определена min( ai[0], 99 ); min(int,int) , и редактор связей выдает сообщение об ошибке: Зачем определять обычную функцию, если ее тин возвращаемого значения и список параметров соответствуют функции, конкретизированной из шаблона? Вспомните, что при вызове конкретизированной функции к ее фактическим аргументам в ходе вывода аргументов шаблона можно применять только ограниченное множество преобразований. Если же объявлена обычная функция, то для приведения типов аргументов допустимы любые трансформации, так как типы формальных параметров обычной функции фиксированы. Рассмотрим пример, показывающий, зачем может потребоваться объявить обычную функцию. Предположим, что мы хотим определить специализацию шаблона функции min<int>(int,int) . Нужно, чтобы именно эта функция вызывалась при обращении к miin() с аргументами люб1х целых типов, пусть даже неодинаков1х. Из-за ограничений, наложенных на преобразования типов, при передаче фактических аргументов разных типов функция miin<int>(int,int) не будет конкретизирована из шаблона. Mi могли бы заставить компилятор выполнить конкретизацию, явно задав аргументы шаблона, однако решение, при котором не требуется модифицировать каждый вызов, предпочтительнее. Определив обычную функцию, мы добьемся того, что программа будет вызывать специальную версию min(int,int) для любых фактических аргументов целых типов без явного указания аргументов шаблона: Если перегрузка разрешилась таким образом, то изменений уже не будет: если позже обнаружится, что в программе нет определения этой функции, компилятор не станет конкретизировать ее тело из шаблона. Вместо этого на этапе сборки мы получим ошибку. В следующем примере программа вызывает, но не определяет обычную функцию определение шаблона функции template <class Type> Type min( Type t1, Type t2 ) { ... } int ai[4] = { 22, 33, 44, 55 }; short ss = 88; void call instantiation() { ошибка: для этого вызова нет функции-кандидата min( ai[0], ss ); обычная функция int min( int a1, int a2 ) { min<int>( a1, a2 ); int main() { call instantiation() { вызывается обычная функция min( ai[0], ss ); Для вызова miin(ai[0],ss) из call instantiation нет ни одной функции-кандидата. Попытка сгенерировать ее из шаблона min() провалится, поскольку для аргумента шаблона Type из фактических аргументов функции выводятся два разных значения. Следовательно, такой вызов ошибочен. Однако при обращении к min(ai[0],ss) внутри main() видимо объявление обычной функции min(int, int) . Тип первого фактического аргумента этой функции точно соответствует типу формального параметра, а второй аргумент может быть преобразован в тип формального параметра с помощью расширения типа. Поскольку для второго вызова устояла только данная функция, то она и вызывается. Разобравшись с разрешением перегрузки функций, конкретизированных из шаблонов, специализацией шаблонов функций и обычных функций с тем же именем, подытожим все, что мы об этом рассказали: 1. Построить множество функций-кандидатов. Рассматриваются шаблоны функций с тем же именем, что и вызванная. Если аргументы шаблона выведены из фактических аргументов функции успешно, то в множество функций-кандидатов включается либо конкретизированный шаблон, либо специализация шаблона для выведенных аргументов, если она существует. 2. Построить множество устоявших функций (см. раздел 9.3). В множестве функций-кандидатов остаются только функции, которые можно вызвать с данными фактическими аргументами. 3. Ранжировать преобразования типов (см. раздел 9.3). a. Если есть только одна функция, вызвать именно ее. b. Если вызов неоднозначен, удалить из множества устоявших функции, конкретизированные из шаблонов. 4. Разрешить перегрузку, рассматривая среди всех устоявших только обычные функции (см. раздел 9.3). a. Если есть только одна функция, вызвать именно ее.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.085
При копировании материалов приветствуются ссылки. |