Search code examples
c++templatesc++17stdstring

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;
}

I'm trying to use getline instead of cin when the type is a string (in order to include whitespace), however I get a bunch of errors saying that I didn't provide enough arguments for std::getline. I've also tried to do this:

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

But I get an error saying I can't convert from 'std::string' to 'T'. How can I make it so it treats T as std::string?

Edit: Here's how I'm calling it:

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';
}

Solution

  • When you call the function with some T other than std::string, then the getline code will not compile, since all the code needs to be compiled regardless of whether the branch is taken, or not.

    To avoid compiling the branch with the getline when not needed, you can use if constexpr, like this:

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

    Here's a demo.