Вот такой вот простой шаблон функции, который возвращает удвоенное значение. Но в параметры я могу писать только числа? (int, double...) Но только числа? Можно ли как то сделать так, чтобы в параметры можно было бы записать еще и строку допустим и на выходе получать что-то типа stringstring или это из области фантастики? Компилятор слово data воспринимает как числа разных типов, или еще может воспринимать как тип данных string например?
template< class TYPE >
void PrintTwice(TYPE data)
{
cout << "Double meaning: " << data * 2 << endl;
}
В вашу шаблонную функцию можно передавать не только числа, а абсолютно все, для чего выражение data * 2 имеет какой-то смысл и возвращает результат, который можно вывести через <<.
Например, если мы перегрузим бинарный * для std::string вот так
std::string operator *(std::string lhs, unsigned rhs)
{
std::string str;
for (; rhs > 0; --rhs)
str += lhs;
return str;
}
то ваш шаблон будет делать именно то, что вы хотите, то есть выводить удвоенную строку
PrintTwice(std::string("test"));
В этом как раз и заключается вся суть шаблонов: они реализуют концепцию duck typing ("утиной типизации"). Им глубоко все равно, что за типы вы в них используете и связаны ли эти типы как-то между собой. Все, что им надо - это чтобы после подстановки этих типов в шаблонный код этот код получался формально правильным.
С этой точки зрения этот вопрос перекликается с вашим же (ныне удаленным) вопросом о том, зачем перегружать оператор << для пользовательского типа Date, если можно обойтись без этого.
На самом деле, перегрузив оператор вывода << для своего типа Date вы тем самым сделали его совместимым с уже существующими средствами стандартной библиотеки. Например, точно так же как мы можем "в одну строку", пользуясь стандартным алгоритмом std::copy, вывести на выход целый массив объектов std::string
std::string mama[] = ( "Mama", "myla", "ramu" };
std::copy(std::begin(mama), std::end(mama), std::ostream_iterator<std::string>(std::cout, "\n"));
мы сможем вывести на выход и массив ваших объектов Date
Date date[] = { ... };
std::copy(std::begin(date), std::end(date), std::ostream_iterator<Date>(std::cout, "\n"));
но только если для вашего Date определен оператор <<.
В данном же случае, определив оператор * для std::string, мы сделали std::string совместимым с вашей функцией PrintTwice.
Однако такой подход - с переопределением оператора * для std::string - следует использовать только в том случае, если такое переопределение является естественным и логичным расширением функциональности std::string. В данном случае ответ на этот вопрос неоднозначен (скорее нет, чем да). Я привел его лишь в качестве примера.
И если вы считаете такое поведение оператора * для std::string ненатуральным, то более правильным способом приспосабливания функции PrintTwice к работе с std::string будет явная специализация (как в ответе @Boris) или, лучше, обычная перегрузка функции
void PrintTwice(const std::string &data)
{
std::cout << "Double meaning: " << data << data << std::endl;
}
В случае если для передаваемого типа перегружен оператор умножения, это должно работать, в противном случае будет вызвана ошибка компиляции.
Вы можете написать специализацию шаблона для строки:
template<>
void PrintTwice(std::string data)
{
std::cout << "Double meaning: " << data + data << std::endl;
}
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости