Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

On the conversion from std::string type to template T type in C++

I’ve found on this forum the following snippet witten by user Ben Voigt:

//forward declaration
template<typename T>
T getline_as(std::istream& s);

template<>
std::string getline_as<std::string>(std::istream& s)
{
    std::string str;
    std::getline(s,str);
    return str;
} 

template<typename T>
T getline_as(std::istream& s)
{
    std::stringstream convert(getline_as<std::string>(s));

    T value;
    convert >> value;
    return value;
}

I am looking for a way to handle possible failures of convert >> value;. My goal would be
to iterate the request to the user to make it insert a given input correctly:

int main()
{
    std::cout << "Please enter a number: ";
    double number{getline_as<double>(std::cin)};
}

My idea was to create a do-while loop inside getline_as but I can’t make it work.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

template<typename T>
T getline_as(std::istream& s)
{
    std::stringstream convert;
    T value;
    do
    {
        convert(getline_as<std::string>(s));
    }
    while(!(convert >> value));
    return value;
}

>Solution :

std::stringstream convert(...); is a constructor call, but trying to do convert(...); after the stream is created is illegal (it would require the stream to overload operator(), which it doesn’t do). convert = std::stringstream(...) would work, but I’d just completely recreate the stream.

You also should use a read-only std::istringstream, since you never write anything to it.

I also made some cosmetic changes and ended up with following:

template <typename T>
[[nodiscard]] T getline_as(std::istream &s);

template <>
[[nodiscard]] std::string getline_as<std::string>(std::istream &s)
{
    std::string str;
    std::getline(s, str);
    return str;
} 

template <typename T>
[[nodiscard]] T getline_as(std::istream &s)
{
    while (true)
    {
        T value{};
        std::istringstream convert(getline_as<std::string>(s));
        if (convert >> value)
            return value;
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading