我正在学习使用模板功能,并在多个文件中组织代码。我看着Why can templates only be implemented in the header file?,他们指出我应该在标头中实现我的模板函数;我还查看了C++ inline functions: declare as such, define as such, or both? Why?,所以知道应该在标头中将完全专用的函数定义为内联;我看着Why use a “tpp” file when implementing templated functions and classes defined in a header?,他们建议在单独的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
答案 0 :(得分:0)
您的解决方案对我来说很好。通常,您可以在ival.h文件的末尾插入ival.tpp文件的代码,因此只有一个头文件。
如何将所有这些与常规功能结合在一起。
通常的规则是:
*.h
文件的最上方放置足够的模板和内联函数声明,以便在调用所有被调用函数之前先对其进行声明。通常只有在特殊情况下才需要这样做。在标头中同时具有模板功能和常规功能时,做上面的事情是正常的吗?
通常不需要在定义模板函数之前显式声明它们,因此通常将其省略。通常仅在少数情况下才需要这样做,即当模板函数相互引用/调用时。调用图中甚至可能存在周期。只需内联声明所有内容,然后将其实际内联的内容留给编译器即可。
将完全专用的功能视为模板还是功能?
将它们作为模板进行处理。所有可以看到通用模板定义的代码也应该可以看到专业化。否则,事情会变得混乱(程序的不同部分对相同的函数使用不同的代码)。
在.cpp中定义模板函数并将其显式实例化为char,int,double,float和std :: string时,我做起来是否更方便?
不。除非有具体理由,否则不要使用显式模板实例化。不要仅使用显式模板实例化来保持头文件的精简。