我正在头文件“ ival.h”中实现模板。我的问题是,这导致模板专业化出现问题。模板专业化是在.cpp中实现的,而不是在模板中的标头中实现的?
我有以下代码:
//In ival.h
#ifndef IVAL_H
#define IVAL_H
#include<string>
#include<sstream>
template <typename T>
bool is_type(std::string);
template<>
bool is_type<int>(std::string);
template<typename T>
T get_type(std::string);
bool yesNo(std::string);
//------------
template <typename T>
bool is_type(std::string Input)
{
std::stringstream ss(Input);
T test;
if (ss >> test)
{
std::string remainder;
ss >> remainder;
return (remainder.size() == 0);
}
else return false;
}
template <>
bool is_type<int>(std::string Input)
{
std::stringstream ss(Input);
int test;
if (ss >> test)
{
std::string remainder;
ss >> remainder;
if (is_type<double>(Input) && remainder[0] == '.')
{
while (remainder[remainder.size() - 1] == '0') remainder.pop_back();
remainder.pop_back();
}
return (remainder.size() == 0);
}
else return false;
}
template<typename T>
T get_type(std::string prompt)
{
T output;
std::cout << prompt;
std::string Input;
while (std::getline(std::cin, Input) && !is_type<T>(Input))
{
std::cout << "Invalid input type. Please try again:\n"
<< prompt;
}
std::stringstream(Input) >> output;
return output;
}
#endif /*IVAL_H*/
并且:
//In ival.cpp
#include "ival.h"
#include <iostream>
#include<sstream>
bool yesNo(std::string prompt)
{
while (true)
{
char output{ get_type<char>(prompt + " [y/n]: ") };
if (output == 'y' || output == 'Y' || output == 'n' || output == 'N') return (output == 'y' || output == 'Y');
std::cout << "Invalid input. Please try again:\n";
}
}
.cpp中的bool yesNo(std::string prompt)
函数尝试将模板与char
一起使用,但由于以下原因而失败:
错误LNK2005:ya sedefinió“ bool __cdecl is_type(class std :: basic_string,class std :: allocator>)”(?? $ is_type @ H @@ YA_NV?$ basic_string @ DU?$ char_traits @ D @ std @@ V?$ allocator @ D @ 2 @@ std @@@@ Z)en ival.obj
如果我从头文件中删除模板功能专业化的定义并将其粘贴到.cpp文件中,问题将消失。为什么会发生这种情况,以及如何将所有定义保留在标题中。
如果我从标头中删除所有模板定义,并将它们包含在.cpp中,并且要显式实例化要与int, char, double, float, std::string
一起使用模板的所有类型,问题也会消失。
第二种方法可以接受吗?对所有类型的实例化似乎不是要做的事情。