Search code examples
c++gccistringstream

Weird behavior of istringstream object instantiated with a null-terminated character string in C++


I have a null-terminated character string stored in s of type char*. I want to create an istringstream object from s. Since the constructor of istringstream expects a parameter of type string, I need to convert s from char* to string. I did this by creating an anonymous string object from s using its constructor in the following way:

istringstream strin(string(s));

This seems OK when compiled using gcc (4.7.3). However, after I added the following codes to use strin

int r;
strin >> r;

I got the compile error:

error: invalid operands of types 'std::istringstream(std::string*) {aka std::basic_istringstream<char>(std::basic_string<char>*)}' and 'int' to binary 'operator>>'

This seems weird to me since I don't understand what the type std::istringstream(std::string*) is. Shouldn't strin be of type std::istringstream?

I can keep the compiler happy by using one of the following modified versions of the code.

Solution 1: pass a named string object

string str(s);
istringstream strin(str);

Solution 2: directly pass s, seems like it will be implicitly converted to string

istringstream strin(s);

Solution 3: explicitly convert s to string

istringstream strin((string)(s));

Solution 4: add a pair of magical parentheses

istringstream strin((string(s)));

Solution 5: tell the compiler s is indeed a char* type

istringstream strin(string((char*)s));

All this works except the original one. Could anybody explain what is really going on here? Thanks.


Solution

  • The most vexing parse strikes again:

    std::istringstream strin( string( s ) );
    

    declares a function (strin) which takes a string as argument, and returns an std::istringstream. (A good compiler could warn here, because there's no way you can possible implement such a function.) The simplest way of correcting this is to add some extra parentheses:

    std::stringstream strin( (string( s )) );
    

    (Actually, the simplest solution here is to just write:

    std::stringstream strin( s );
    

    and let the implicit conversion do the job.)