Разница между явной специализацией и обычными функциями при перегрузке шаблонной функции - PullRequest
13 голосов
/ 13 мая 2011

Я сегодня в движении.Здесь вопрос n00b номер 7:

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

Какова подходящая ситуация для использования явной специализации?Я не совсем понимаю:

#include <iostream>

template <typename s> void test(s var1);
template <> void test<int>(int var1);

int main(){
    test(1);
    test(1.1);
    test("hello!!");
    return 0;
}

template <typename s> void test(s var1){
    std::cout << var1 << std::endl;
}

template <> void test<int>(int var1){
    std::cout << "int " << var1 << std::endl;
}

В отличие от:

#include <iostream>

template <typename s> void test(s var1);
void test(int var1);

int main(){
    test(1);
    test(1.1);
    test("hello!!");
    return 0;
}

template <typename s> void test(s var1){
    std::cout << var1 << std::endl;
}

void test(int var1){
    std::cout << "int " << var1 << std::endl;
}

Ответы [ 5 ]

6 голосов
/ 13 мая 2011

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

Если вы собираетесь объявить и определить функцию внутри файла заголовка, который является , а не шаблоном-функцией, вы должны будете объявить функцию как inline. Это связано с тем, что функция шаблона не является реальной функцией, которая связана с модулем кода до тех пор, пока она не будет реализована. Затем компоновщик отбрасывает это создание после компиляции модуля кода. Если компоновщик не сделал этого, то каждый раз, когда файл .cpp включал заголовочный файл, компоновщик жаловался бы на дубликаты определений для функции. Использование ключевого слова inline в функции, не связанной с шаблоном, имеет аналогичный эффект на уровне компилятора, поскольку всякий раз, когда функция используется в файле .cpp, компилятор заменяет этот вызов функции телом кода функции из inline функция в заголовочном файле и позволяет избежать накладных расходов при вызове функции с помощью связанной и активной настройки и очистки записи стека. Поэтому компоновщик не будет жаловаться на дубликаты определений для функции.

3 голосов
/ 21 июля 2012

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

3 голосов
/ 13 мая 2011

Главное отличие: явные специализации вообще не участвуют в перегрузке.

template<typename T> void f(T const&);
template<> void f<char const*>(char const * const&);

Вызов с f("hello") не учитывает никаких явных специализаций. Он будет принимать только все шаблоны и выводить их аргументы. Выше T будет выведено до char[6], поэтому специализация не будет выбрана.

Если вместо этого вы перегрузите шаблон функции, у вас будут совершенно другие характеристики.

template<typename T> void f(T const&);
void f(char const * const&);

Вызывая это, он выберет вторую функцию, потому что как параметр (char const(&)[6]) сгенерированной специализации, так и параметр (char const * const&) одинаково хорошо соответствуют аргументу, но вторая функция - это не шаблонная функция, поэтому она предпочтительнее в конце концов.

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

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

0 голосов
/ 13 мая 2011

ИМХО, явная специализация для function template должна использоваться, когда вы собираетесь вызывать эту функцию, используя явный аргумент шаблона.например,

test<int>(myClass); // no argument for 'int' -> declare test() as template specialization

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

test(10, myClass); // argument 10 is 'int' -> test() should be normal specialized

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

...