Вот такой вот простой шаблон функции, который возвращает удвоенное значение. Но в параметры я могу писать только числа? (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;
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Недавно я уже задавал несколько вопросов по моей программе-шифровщику, но теперь у меня появился новый (уже окончательный) вопросДело в том,...
Нужно отправить пакет (под видом клиента) на сервер Minecraft PE и получить ответНашел статью на вики, описывающую взаимодействия клиента и сервера,...
Сортирую интовый вектор, не мог понять как происходит выход за границы массивы, вот код: