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.
