Search code examples
c++templatesinputc++20auto

Can I use template or auto keyword in C++ to create a variable that I can use with std::cin to get a value from user?


This line of code is wrong and won't compile, and I am wondering how it can be fixed.

#include <iostream>

template <typename T>

auto getValue()
{
    std::cout << "Enter an integral value: ";
    T value{};
    std::cin >> value;
    // I would do input handing later
    return value;
}

int main()
{
    auto value1{getValue()};
    std::cout << value1 << '\n';
}

Please point out if there is a way to make it possible or if it is not possible then why?

I want to receive an integral value from the user and create a variable depending on the value that they entered.

For example, if they entered 56, then an integer variable will be created. And if they entered 56.78, then a double variable will be created since it is a fractional value.


Solution

  • Types are fixed at compile time so your code can't work. If you really need to do this then there are a few approaches.

    1. The javascript approach of just using double everywhere, a double can hold 53 bit integers without losing precision.
    2. Return a std::variant

    Option 2 could look something like this:

    #include <variant>
    #include <iostream>
    #include <string>
    #include <optional>
    
    std::optional<int> parseInt(const std::string& str)
    {
        try
        {
            size_t pos;
            int value = std::stoi(str, &pos);
            if (pos == str.size())
            {
                return value;
            }
        }
        catch (std::exception&)
        {
        }
        return {};
    }
    
    std::optional<double> parseDouble(const std::string& str)
    {
        try
        {
            size_t pos;
            double value = std::stod(str, &pos);
            if (pos == str.size())
            {
                return value;
            }
        }
        catch (std::exception&)
        {
        }
        return {};
    }
    std::variant<int, double> getValue()
    {
      while (true)
      {
        std::cout << "Enter a numerical value: ";
        std::string str;
        std::getline(std::cin, str);
        auto i = parseInt(str);
        if (i)
        {
            return *i;
        }
        auto d = parseDouble(str);
        if (d)
        {
            return *d;
        }
        throw std::invalid_argument("invalid input");
      }
    }