перегрузка шаблона функции

Кто-либо может суммировать идею перегрузки шаблона функции? Какие вопросы, шаблонный параметр или параметр функции? Что относительно возвращаемого значения?

Например, учитывая шаблон функции

template<typename X, typename Y> void func(X x, Y y) {}

каков шаблон перегруженной функции?

1) template<typename X> void func(X x, int y) {}
2) template<typename X, typename Y> X func(X x, Y y) {}
3) template<class X, class Y, class Z> void func(X x, Y y, Z z) {}
22
задан Leushenko 18 May 2018 в 09:21
поделиться

4 ответа

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

Вы можете использовать два других:

template<typename X> void func(X x, int y);

будет использоваться, если вторым аргументом вызова является INT, например, FUNC («String», 10);

template<class X, class Y, class Z> void func(X x, Y y, Z z);

будет использоваться, если вы звоните Func с тремя аргументами.


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

14.5.5

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

Нераспределенный (или «менее шаблон») перегрузка является предпочтительной для шаблонов, например, E.G

template <class T> void foo(T);
void foo(int);

foo(10); //calls void foo(int)
foo(10u); //calls void foo(T) with T = unsigned

Ваша первая перегрузка с одним параметром без шаблона также падает в соответствии с этим правилом.

Учитывая выбор между несколькими шаблонами, предпочтительнее более специализированных матчей:

template <class T> void foo(T);
template <class T> void foo(T*);

int i;
int* p;
int arr[10];

foo(i);  //calls first
foo(p);   //calls second
foo(arr); //calls second: array decays to pointer

Вы можете найти более официальное описание всех правил в той же главе стандарта ( шаблонов функций )


и Наконец, есть некоторые ситуации, когда две или более перегрузки были бы неоднозначными:

template <class T> void foo(T, int);
template <class T> void foo(int, T);

foo(1, 2);

здесь вызов неоднозначен, потому что обе кандидаты одинаково специализируются.

Вы можете неоднозначить такие ситуации с использованием (например) Boost :: Disable_if . Например, мы можем указать, что при t = int, то вторая перегрузка не должна быть включена в качестве кандидата в перегрузку:

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
template <class T>
void foo(T x, int i);

template <class T>
typename boost::disable_if<boost::is_same<int, T> >::type
foo(int i, T x);

foo(1, 2); //calls the first

здесь библиотека производит «сбой замены» в типе возврата второй перегрузки, если t = = = INT, удаляя его от набора перегрузки кандидатов.

На практике вы должны редко бегать в таких ситуациях.

30
ответ дан 29 November 2019 в 05:03
поделиться

Вы не можете использовать CoreData для поиска ближайшего объекта, но можете сузить запрос с помощью ограничивающей рамки. Чтобы найти ближайший объект, вы можете предпочесть использовать просто разницу lat/long, которая значительно быстрее, чем вычисление фактических расстояний.

У меня был аналогичный вопрос:

CoreData: Найдите минимум вычисленного свойства

-121--1534886-

НЕ ПЫТАЙТЕСЬ , чтобы избежать изучения цели-C, если вы собираетесь писать приложения для Mac. Цель PyObjC и других языковых привязок - позволить вам повторно использовать существующие

-121--2654205-

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

1
ответ дан 29 November 2019 в 05:03
поделиться

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


. Рассмотрим шаблон, чтобы быть как до-процессор макроса, который расширяет #defines, прежде чем компилятор увидит их.

Компилятор «расширяет» ваши параметры шаблона, а затем посмотрите на ваши объявления функций. Таким образом, параметр шаблона == параметр функции. Если вы объявите ту же функцию дважды, вы получите ошибку.

Вы спрашиваете о возвращенном типе. Это часть «подписи функции». Две функции с одинаковыми параметрами, но разные типы возврата - это две разные функции.

1
ответ дан 29 November 2019 в 05:03
поделиться

Здесь есть две отдельные вещи: шаблон функции и перегрузка функций. Любые два отчетных декларации шаблонов, вероятно, будут перегрузки друг друга, поэтому ваш вопрос не имеет смысла, как указано. (Три «перегрузки», которые вы даете, не создаете на первый шаблон, скорее у вас есть четыре перегрузки к той же названию функции.) Реальная проблема, учитывая некоторые перегрузки и вызов , как позвонить Желаемая перегрузка?

Во-первых, тип возврата не участвует в процессе перегрузки, не включен ли шаблон. Так что № 2 никогда не будет хорошо играть с # 1.

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

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

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

template< typename X, typename Y >
struct functor {
    void operator()( X x, Y y );
};
template< typename X > // partial specialization: 
struct functor< X, int > { // alternative to overloading for classes
    void operator()( X x, int y );
};

Теперь вы пожертвоваете синтаксисом неявного инсультации (без угловых кронштейнов). Если вы хотите вернуть это, вам нужна другая функция

template< typename X, typename Y > void func( X x, Y y ) {
    return functor< X, Y >()( x, y );
}

Мне было интересно услышать, может ли перегрузить функцию что-либо (помимо вычета), что класс [частичная] специализация не может ...

, а затем, конечно, Ваша перегрузка № 3 никогда не будет сталкиваться с двусмысленностью, потому что она имеет разное количество аргументов, чем любая другая перегрузка.

3
ответ дан 29 November 2019 в 05:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: