I am implementing my templates in a header file "ival.h". My problem is that this is causing some problem with a template specialization. Are template specializations implemented in .cpp rather than in headers as templates are?
I have the following code:
//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*/
And:
//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";
}
}
The bool yesNo(std::string prompt)
function in .cpp attempts to use the templates with char
but it fails as:
error LNK2005: ya se definió "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
The problem disappears if I remove the definition of the template function specialization from the header file and paste it into the .cpp file. Why is this happening, and how can I keep all the definitions in my header.
The problem also disappears if I remove all template definitions from header and include them in .cpp with explicit instantiation to all types I want to use the templates with i.e int, char, double, float, std::string
.
Is this second approach acceptable? Instantiation to all the types seems as not the thing to do.