我如何将std::getline转换成模板类型?

How do I std::getline into a template type?

template <typename T>
T getUserInput(std::string prompt = "")
{
    T input;
    std::cout << prompt;
    if (std::is_same<T, std::string>::value)
    {
        std::getline(std::cin, input);
    }
    else
    {
        std::cin >> input;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    return input;
}

当类型为字符串时(为了包含空格),我尝试使用 getline 而不是 cin,但是我收到一堆错误,说我没有为 [=24= 提供足够的参数].我也试过这样做:

    if (std::is_same<T, std::string>::value)
    {
        std::string sInput = "";
        std::getline(std::cin, sInput);
        return sInput;
    }

但是我收到一条错误消息,提示我无法从 'std::string' 转换为 'T'。我怎样才能让它把 T 当作 std::string?

编辑: 我是这样称呼它的:

int main()
{
    int x = getUserInput<int>("Please type a number: ");
    std::cout << x << '\n';
    std::string test = getUserInput<std::string>("Please type a string: ");
    std::cout << test << '\n';
}

当你用 T 而不是 std::string 调用函数时, getline 代码将无法编译,因为无论是否分支,所有代码都需要编译是否被采取。

为避免在不需要时使用 getline 编译分支,您可以使用 if constexpr,如下所示:

if constexpr (std::is_same_v<T, std::string>)
{
    std::getline(std::cin, input);
}
else
{
    std::cin >> input;
}

这是 demo

除了 if constexpr 之外的另一个选项(没有任何问题)是函数重载 and/or 专业化,例如:

// default version if not specialized
template<typename T>
T doUserInput()
{
    T input;
    std::cin >> input;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    return input;
}        

template<>
std::string doUserInput() 
{
    std::string s;
    std::getline(std::cin, s);
    return s;
}

template <typename T>
T getUserInput(std::string prompt = "")
{
    std::cout << prompt;
    return doUserInput<T>();
}