• Debra (unregistered)

    Actually, calling operator void* (though it would be a bit more readable with a static_cast instead of an explicit operator call) was a very valid way of checking the stream state up until C++11. That conversion was removed in C++11 and replaced with a conversion of the stream to bool, which means that the return statement of this function could just say return iss && iss.eof(). My guess would be that changing the compiler also changed the default C++ standard that the code is compiled with. Maybe that's a WTF right there.

  • (nodebb)
    bool str2val(const string &s, int &v) {
        std::istringstream iss(s);
        istream &i = (iss >> v);
        bool b = (!(i.fail() || i.bad())) && iss.eof();
        return b;
    }
    

    Is not how I'd do it, as there's no reason to capture the return from iss >> v because that return will be a reference to iss itself, so you can ask iss directly:

    bool str2val(const string &s, int &v) {
        std::istringstream iss(s);
        iss >> v;
        return (!(iss.fail() || iss.bad())) && iss.eof();
    }
    

    What's worse is that the original version tests the state via i, but also directly onto iss...

  • (nodebb)

    Isn't there a version of atoi in modern libraries which doesn't require creating objects and works in a C++ way? Like int.Parse in C#

  • Greg (unregistered) in reply to Mr. TA

    Yes there is; the function is named stoi: https://www.cplusplus.com/reference/string/stoi/

  • (nodebb) in reply to Mr. TA

    std::stoi() apparently if using C++11 or greater.

    https://stackoverflow.com/questions/7663709/how-can-i-convert-a-stdstring-to-int

  • Sole Purpose Of Visit (unregistered) in reply to Jeremy Pereira

    I think I prefer std::from_chars, which is available in C++17. (Probably also available in various TRs for C++11, but I haven't checked.)

    The question we should be asking is, what happens if you supply a string which is "almost" an integer? Apparently std::stoi will parse "11x" as "11", which is clearly wrong. So you'd need to use a regexp to sanitise the input , which seems extreme. std::from_chars at least includes an optional parameter for the base, which makes sense to me.

    And it's reasonable to complain about the various messy bits of the standard library, but then you're still faced in the OP with a construct that does something "magical" with a strstream, and you probably don't understand the edge cases (I don't), so you're no better off with any version of the hand-crafted string parsing thing.

    To Debra: Yes. In fact, the default in 4.x -> 5.x went from gnu89 to gnu11, which is very, very likely to be a breaking change. Also a long overdue one IMHO. And I would prefer my C++ gurus (or even cow-orkers) to understand that going from one major version of the compiler to another major version is very very likely to do this, so it's only a WTF in that nobody in the OP dev environment appeared to expect it.

    All in all, an entertaining post about operator overloading, except not really, because a C++ programmer is expected to understand operator << on strings in precisely the same way that they are expected operator + on integers. It gets a bit dicier with operator ++, what with the overload for pre and post, but C++ programmers are expected to understand those too.

    Calling out the operator explicitly in a "fluid" fashion -- let alone calling out the cast operator in a fluid fashion -- is, however, evidence of a diseased mind.

  • my name is missing (unregistered)

    C++ is to foot guns as an A-10 gatling gun is to a pea shooter

  • (nodebb)

    I looked at a stoi as well as other suggestions on StackOverflow and it looks like the closest there is in C++ to a validated string to number parsing is Qt library. It behaves like int.TryParse in .NET, which is as close as possible to the perfect behavior for this kind of operation.

  • (nodebb)

    I've been thinking about this some more, and it's starting to seem like someone who'd have used sscanf to do it in C back in the day. It's surprisingly simple to do once you know the incantation, but desperately fragile, while this thing with stringstreams suffers from slowness and opacity, but is far less fragile.

  • kind of related (unregistered)

    Relatedly, at long last, C++20 finally introduced the Formatting Library (https://en.cppreference.com/w/cpp/utility/format) as part of STL. That one was badly needed (unless you just used Boost).

    In response to SPOV's question about "11x" vs "11" - that's what the iss.eof() checks. If the istringstream is done parsing the "11" and is looking at an "x" instead of EOF, it'll fail that check. What can be frustrating is that trailing spaces will trip it as well (especially frustrating because trimming a string is not a simple STL call)

  • LCrawford (unregistered)

    Relatedly, at long last, C++20 finally introduced the Formatting Library

    TRWTF is the C++ library lacking a decent implementation of something so common as string->int for so long. The fixed WTF is much more elegant in retrospect and even the original WTF is not as bad as it seemed.

  • The Shadow (unregistered)

    You often get things like this in really old code, possibly ported from a different languages, where features simply didn't exist.

  • Sole Purpose Of Visit (unregistered) in reply to kind of related

    True, yes, that's what the eof checks. But being told that you fail because the parser can't understand the string format of the integer isn't really all that useful, is it?

  • Gaetan (unregistered)

    Original submitter here, Yeah, part of the WTF is definitely me not knowing much (yet) about that part of C++:

    • Steve : I do feel ashamed I didn’t think about keeping ’iss’ all the way ... ;
    • Debra: right you are! I had suspected this standard thing but missed it in the standards (I found it all right this morning).
    • The Shadow : oh yes, at least 15 years old, possibly 20;
    • Sole Purpose of Visit : right, part of the WTF is that I don’t know which compiler my colleagues will use ... (though that should get better soon) so I have to find something that works for pre/post C++11 standards for the time being. Thanks for the informed comments all of you.
  • Charles (unregistered)

    @kind of related: "What can be frustrating is that trailing spaces will trip it as well"

    That's because you need to approach parsing the right way - not divide the input into pieces and parse each piece, but go strictly left to right. So parsing an integer using std::stoi() should use the pos parameter to find out where parsing stopped and then check that what followed the integer is appropriate. That not only makes the plain integer case easy, it also makes much more complex cases easy. For example, if you want to accept things like "10K" for 10000 or "10*57" is you're accepting some form of expression.

  • Gaetan (unregistered)

    Original submitter still, for a last confession (Sunday is a good time for it too): past me came back with a big stick and hit me hard with it calling me a moron. Why? As probably happens to any half-decent C++ programmer, years ago I needed something like this, and I had written " (iss >> v) && iss.eof()" for the very reasons mentioned in the comments (it does the job and it works before and after C++11). So why not use it this time? Well I was so puzzled by this bizarre explicit call to "operator void*()" that I forgot the big picture. In other words I was "overloaded with details", and I suspect even Remy did not realize how accurate his title was.

Leave a comment on “Getting Overloaded With Details”

Log In or post as a guest

Replying to comment #:

« Return to Article