C ++ - правила вокруг реализации шаблона функции - PullRequest
1 голос
/ 09 декабря 2011

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

#include <iostream>

template <typename>
int check(int x) {
  return x * 2;
}

int main() {
  std::cout << check<double>(10) << std::endl; // #1
  std::cout << check<>(10) << std::endl;         // #2
  std::cout << check(10) << std::endl;            // #3
  return 0;
}

Строки # 1, # 2 и # 3 не скомпилированы все вместе, при каждой попытке я оставляю только одну из них и комментирую остальные.Итак, когда # 1 включен, у меня нет ошибок компиляции, и выводится правильный ответ «20».Как я понимаю, "check <" double ">" вызывает механизм создания шаблона, поэтому функция "int check (int)" действительно создана (тип параметра шаблона не имеетлюбое влияние).Когда # 3 включен, у меня ошибка компиляции "ошибка: не найдена соответствующая функция для вызова 'check (int)'" , что разумно, так как я пытаюсь вызвать "check(int) " функция, которая не существует.Мой вопрос касается случая № 2: в этом случае я получаю ту же самую ошибку ": нет соответствующей функции для вызова 'check (int)'" .Разве не должен вызывать "check <> (10)" механизм запуска шаблона также?

Ответы [ 5 ]

1 голос
/ 09 декабря 2011

Вы не помещаете никаких параметров шаблона в <>.Как компилятор может узнать, какую функцию шаблона нужно создать?Обратите внимание, что ваша функция шаблона:

template <typename>
int check(int x) 

Если вы измените ее на:

template <typename T>
int check(T x) 

, тогда проверка <> (10) должна подойти, потому что компилятор может знать типиз параметра.

0 голосов
/ 09 декабря 2011

Единственный экземпляр шаблона, который вы получите, -

check<double>(10)

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

template<typename T>
T check(T x) {
  return x*2;
}

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

check(10.0);   // instantiates check<dobule>
check(3);      // instantiates check<int>

или

a = MyObject();
check(a);         // instantiates check<MyObject>
0 голосов
/ 09 декабря 2011

Я должен сказать, что обычно шаблон не так: (

Попробуйте это:

template<typename T>
T check(T x){
    return x*2;
}
0 голосов
/ 09 декабря 2011

#2 будет допустимым, если аргумент шаблона может быть выведен.

#include <iostream>

template <class T>
void foo(T t)
{
    std::cout << "Template " << t << '\n';
}

void foo(int n)
{
    std::cout << "Not template " << n << '\n';
}

int main()
{
    foo(10); //calls non-template function 
             //because matching non-template preferred over function templates

    foo<>(10); //calls the template function, empty brackets indicate you want
               //the template overload, type is deduced from passed argument.

}

Еще одна возможность, если шаблон функции имеет аргументы по умолчанию (только в C ++ 11).

template <class T = void>
int foo()
{
    return 10;
}

int main()
{
    return foo<>(); //same as foo<void>();
}
0 голосов
/ 09 декабря 2011

Если вы не передаете аргумент шаблона, это эквивалентно поиску функции без аргумента шаблона (т. Е. Он не создает экземпляр шаблона). Добавленный <> ничего не значит в этом случае, потому что нет перегрузки.

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

template <typename T>
T check(T x) {
    return x * 2;
}

Тогда все 3 случая будут работать, так как он выводит тип T. См. https://stackoverflow.com/a/797632/888641 для более подробного объяснения.

Примечание: вы можете использовать typename или class, здесь они делают то же самое.

...