0

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.

Daniel Duque
  • 159
  • 9
  • How is this a duplicate from [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) I am implementing my templates in the header as pointed out in that question. My problem is Why this is NOT working with a template specialization. – Daniel Duque Feb 10 '19 at 18:46
  • You can keep your implementation in the header by declaring the functions inline. – john Feb 10 '19 at 19:01
  • If the the same function definition appears in multiple translation units (if it is in the header and that header included by multipel cpp files), then this function definition has to be marked with `inline`. So it has to be `... inline bool is_type( ...` for all of your definitions in in the header. – t.niese Feb 10 '19 at 19:03

0 Answers0