Как организовать шаблон-функции и функции в заголовках и исходных файлах - PullRequest
0 голосов
/ 11 февраля 2019

Я учусь использовать функции шаблонов и организовывать свой код в несколько файлов.Я посмотрел на Почему шаблоны могут быть реализованы только в заголовочном файле? , где они указывают, что я должен реализовать свои функции шаблона в заголовке;Я также посмотрел на встроенные функции C ++: объявить как таковой, определить как таковой или и то, и другое?Почему? , поэтому я знаю, что должен определять полностью специализированные функции как встроенные в заголовок;и я посмотрел на Зачем использовать файл "tpp" при реализации шаблонных функций и классов, определенных в заголовке? , где они предлагают определять шаблоны (а также полностью специализированные шаблоны?) в отдельном my.tppи добавьте #include "my.tpp" в конце моего заголовка.

Теперь мой вопрос как у начинающего: как мне объединить все это с обычными функциями.

Представьте себе следующее:

#ifndef IVAL_H
#define IVAL_H

//Function to determine if input string is of a given type
template<typename T>
bool is_type(std::string);

//Specialization when testing integer
//As I also want to accept  e.g. 4.0000 as an integer
template<>
bool is_type<int>(std::string);

//Function to get a given type
template<typename T>
T get_type(std::string);

//Finally a normal function to ask for [y/n]
bool yesNo(std::string prompt);

//Include templates definitions
#include"ival.tpp"

#endif /*IVAL_H*/

Тогда у меня есть, как и предлагалосьв приведенных выше вопросах:

//in ival.tpp
#ifndef IVAL_TPP
#define IVAL_TPP

template<typename T>
bool is_type(std::string input)
{
//How to validate input
}

template<>
bool inline is_type<int>(std::string input)
{
\\How to validate when integer
}

template<typename T>
T get_type(std::string prompt)
{
//How to keep asking until valid input
//Using is_type
}
#endif /*IVAL_H*/

И, наконец, .cpp моя обычная функция:

//in ival.cpp
#include "ival.h"

bool yesNo(std::string prompt)
{
//How to ask for [y/n]
//Using get_type<char>
}

Это вызывает некоторую путаницу относительно того, как правильно организовать свои функции,Когда в заголовке у нас есть и шаблонные функции, и обычные функции, нормально ли делать то, что я делал выше?(другой исходный файл для нормальных функций) - это полностью специализированные функции, которые обрабатываются как шаблон (т. е. определены встроенными в файле, где находятся все шаблоны) или как функция (т. е. определены только в .cpp, как и все другие функции).

Это то, что я сделал удобнее, чем определение шаблонных функций в .cpp и явное создание экземпляров char, int, double, float и std::string

1 Ответ

0 голосов
/ 11 февраля 2019

Ваше решение выглядит хорошо для меня.Обычно вы можете вставить код файла ival.tpp в конец файла ival.h и, таким образом, иметь только один заголовочный файл.

Как мне объединить все это с обычными функциями.

Обычные правила:

  • Поместите только определения ваших обычных функций в файл * .cpp.
  • Поместите все определения функций вашего шаблона, определения встроенных функцийи регулярные объявления функций в вашем файле * .h (или некоторые любят называть его * .hpp).Выберите порядок, чтобы большинство функций использовало / вызывало только те функции, которые определены над ними.
  • Только при необходимости (например, циклические зависимости): поместите только достаточно шаблона и встроенной функции объявления на оченьначало файла *.h, поэтому все вызываемые функции объявляются до их вызова.Это обычно необходимо только в экзотических случаях.

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

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

Полностью специализированные функции обрабатываются как шаблон или как функция?

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

Это то, что я сделал удобнее, определяя функции шаблона в .cpp и явно создавая экземпляры для char, int, double, float и std :: string?

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

...