Why does "auto" declare strings as const char* instead of std::string?

11,254

Solution 1

The reason you can't "write" to your auto variable is that it's a const char * or const char [1], because that is the type of any string constant.

The point of auto is to resolve to the simplest possible type which "works" for the type of the assignment. The compiler does not "look forward to see what you are doing with the variable", so it doesn't understand that later on you will want to write into this variable, and use it to store a string, so std::string would make more sense.

You code could be made to work in many different ways, here's one that makes some sense:

std::string default_name = "";
auto name = default_name;

cin >> name;

Solution 2

Because string literals have type const char[N+1], not std::string.

This is just a fact of the language.

They could have made it so that auto has a special case for string literals, but that would be inconsistent, surprising and of very little benefit.

Solution 3

If you use string literals, auto will work as expected.

In C++14, C++17 or C++20, you can place an s after the quotes, and it will create a std::string instead of a const char* string.

This can be used together with auto to create a std::string:

auto hello = "hello"s;

String literals are not enabled by default. One way of enabling string literals is to place the following at the top of the source file:

#include <string>
using namespace std::string_literals;  

As an example, this loop works for std::string (with s added to the string literal), but not for const char* type string literals:

for (auto &x : hello) {                                                                        
    std::cout << "letter: " << x << std::endl;                                                         
}

Here is the cppreference page for the ""s operator.

Share:
11,254
Magnus
Author by

Magnus

trying to constantly improve things.

Updated on July 19, 2022

Comments

  • Magnus
    Magnus almost 2 years

    I made a template which adds the data it is given. If I use it like this, the compiler declares in_1 and in_2 as const char *, and the code doesn't compile.

    #include <iostream>
    using namespace std;
    template <class T>
    T addstuff(T part_1, T part_2){
        return(part_1+part_2);
    }
    
    int main(int argc, char const *argv[])
    {
        auto in_1="Shut ";
        auto in_2="up.";
        cout<<addstuff(in_1, in_2)<<endl;
        return 0;
    }
    

    If I declare in_1 and in_2 std::string, it works like a charm.

    Why can't (or doesn't) the compiler declare those strings automatically std::string?

  • Joseph Mansfield
    Joseph Mansfield over 10 years
    @H2CO3 Without the reference.
  • Admin
    Admin over 10 years
    To be precise, string literals are of type const char [length + 1], but they of course decay into a pointer.
  • user4815162342
    user4815162342 over 10 years
    You might want to change "string constant" to "string literal" in the first paragraph, because a string constant might be reasonably understood as a constant std::string.
  • M.M
    M.M over 8 years
    It'd be good if this answer also explained why in_1 does not have type const char[6]