在标头中使用模板专用化问题

时间:2019-02-10 18:37:56

标签: c++ header-files function-templates

我正在头文件“ 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一起使用模板的所有类型,问题也会消失。

第二种方法可以接受吗?对所有类型的实例化似乎不是要做的事情。

0 个答案:

没有答案