Параметры шаблона функции

228
14 января 2018, 05:34

Вот такой вот простой шаблон функции, который возвращает удвоенное значение. Но в параметры я могу писать только числа? (int, double...) Но только числа? Можно ли как то сделать так, чтобы в параметры можно было бы записать еще и строку допустим и на выходе получать что-то типа stringstring или это из области фантастики? Компилятор слово data воспринимает как числа разных типов, или еще может воспринимать как тип данных string например?

template< class TYPE >
void PrintTwice(TYPE data)
{
    cout << "Double meaning: " << data * 2 << endl;
}
Answer 1

В вашу шаблонную функцию можно передавать не только числа, а абсолютно все, для чего выражение 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;
}
Answer 2

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

Вы можете написать специализацию шаблона для строки:

template<>
void PrintTwice(std::string data)
{
    std::cout << "Double meaning: " << data + data << std::endl;
}
READ ALSO
Сборка MySQL Connector/C++: отладочная версия

Сборка MySQL Connector/C++: отладочная версия

Не могу собрать MySQL Connector/C++ win32 debug

212
Проблемы с шифровкой файла

Проблемы с шифровкой файла

Недавно я уже задавал несколько вопросов по моей программе-шифровщику, но теперь у меня появился новый (уже окончательный) вопросДело в том,...

173
Как отправить RakNet пакет и получить ответ?

Как отправить RakNet пакет и получить ответ?

Нужно отправить пакет (под видом клиента) на сервер Minecraft PE и получить ответНашел статью на вики, описывающую взаимодействия клиента и сервера,...

406
Сортировка вставками C++(std::vector&lt;int&gt;)

Сортировка вставками C++(std::vector<int>)

Сортирую интовый вектор, не мог понять как происходит выход за границы массивы, вот код:

197