Stallman Stallman - 10 days ago 8
C++ Question

Is it safe to use double quote to initialize string as using generic algorithm in C++?

I am studying the C++ Primer 5th edition. On page 479, it mentions that


string sum = accumulate(v.cbegin(), v.cend(), "");
is not correct since
no + on const char*
for "";


The type of
v
is a sequential container such as a vector.

I found that using double quotes to create a string is dangerous, especially for the condition that you use generic algorithm, since it requires the objects' defined operator.

But I can't figure out what the description
no + on const char*
means?


  1. Will it call the constructor
    string (const char* s);
    which is defined in c-string?

    I think that's what the compiler does as it interprets the string which are initialized with quotes in C++.

  2. Should we create a string with double quotes? It will cause
    overriding on operators
    failed.


Answer

What it's saying is that you can't add pointers to [const] char to each other, nor can you add a char to a char [const] * (well, technically, you can add a char to a char *, but it won't do what you want--it'll basically treat the char * as if it points to the beginning of an array, and treat the char as an index into that array, so the result will be a char * offset by some distance from the original, where the distance is equal to the encoded value of the char you added).

std::accumulate deduces the type it should use for the summation from the type of the value you pass as the third parameter. It tries to add things using that type, then when it's done, it attempts to return that value (then, in this case the assignment would attempt to convert char const * to std::string). That final conversion would work fine, but the intermediate additions would not.

To make it work, you need to pass an actual std::string as the initial value:

string sum = accumulate(v.cbegin(), v.cend(), string());

This way it will deduce the summation type as std::string, so it'll be adding items to a string instead of trying to add to a char const *. If you're compiler is new enough, you could get the same effect with:

string sum = accumulate(v.cbegin(), v.cend(), ""s);

C++11 added a "user defined literal" feature that allows a suffix like this to invoke a constructor for an object type. C++14 added a number of predefined suffixes like this, including 2 that use the s suffix like this--this one (for a string literal) creates a std::string. The other (for integers) creates a timing value used with the std::chrono timing classes/functions, so 3s means "three seconds".

Comments