如何在头文件和源文件中组织模板函数和函数

How to organize template-functions and functions, in headers and source files

本文关键字:函数 源文件 文件      更新时间:2023-10-16

我正在学习使用模板函数并将代码组织在多个文件中。我看了为什么模板只能在头文件中实现?他们指出我应该在头中实现我的模板函数;我还研究了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, floatstd::string

您的解决方案对我来说很好。您通常可以在文件ival.h的末尾插入文件ival.tpp的代码,因此只有一个头文件。

如何将所有这些与正则函数结合起来。

通常的规则是:

  • 只将正则函数的定义放入*.cpp文件中
  • 将所有的模板函数定义、内联函数定义和正则函数声明放在*.h文件中(或者有些人喜欢将其称为*.hpp)。选择一个顺序,使大多数函数只使用上面定义的/call函数
  • 仅在必要时(例如循环依赖项):在*.h文件的最顶部放置足够的模板和内联函数声明,以便在调用所有被调用的函数之前对其进行声明。这通常只有在特殊情况下才有必要

当在一个头中我们有模板函数和普通函数时,做我上面做的事情是正常的吗?

通常不需要在定义模板函数之前显式声明模板函数,因此这一点经常被省略。这通常只在少数必要的情况下进行,即当模板函数相互引用/调用时。调用图中甚至可能存在循环。只需将其全部声明为内联,并将其实际内联内容留给编译器。

完全专业化的函数是作为模板处理还是作为函数处理?

将它们视为模板。所有能够看到通用模板定义的代码也应该能够看到专门化。否则事情就会变得一团糟(程序的不同部分对同一个调用的函数使用不同的代码)。

在.cpp中定义模板函数并显式实例化为char、int、double、float和std::string时,我所做的是否更方便?

否。除非你有具体的理由,否则不要使用显式模板实例化。不要为了保持头文件的精简而使用显式的模板实例化。