Search code examples
c++stdstring

Possible to modify named std::string on construction?


Does anyone know why the commented line fails compilation but the uncommented line is okay?

#include <iostream>

int main()
{
    // std::string foo("hello").erase(2); // This doesn't compile...
    std::string("hello").erase(2);        // ...but this does.
}

Including the commented line causes this error:

main.cpp: In function ‘int main()’:
main.cpp:5: error: expected ‘,’ or ‘;’ before ‘.’ token

Can someone explain what the rules are about modifying anonymous versus named std::string objects right where they are constructed?


Solution

  • This is an issue that has to do with the syntax for the language. There's a distinction between a declaration, which is a statement, and a creation of a temporary, which is an expression. The two are handled quite differently by the language and are subject to different rules.

    A declaration is a statement in which you give the type of a variable, the name, and some expression that initializes it. So, for example, you could write

    std::string foo("hello");
    

    or

    std::string foo = "hello";
    

    However, you cannot write

    std::string foo("hello").erase(2);
    

    simply because the language says that that syntax isn't allowed there. I mean, I get what you're saying, and I think most people probably would as well, but the language says that you're not allowed to do that. You could, however, write

    std::string foo = std::string("hello").erase(2);
    

    because declaration statements do allow you to provide arbitrary expressions as initializers.

    On the other hand, the expression

    std::string("hello").erase(2)
    

    is perfectly well-formed as an expression, because expressions can be built by creating temporary objects or calling member functions on different objects.

    So really, there's no reason why the language couldn't have been designed so that what you're doing would be legal, but it just wasn't designed that way.