After C++11, I thought of c_str()
and data()
equivalently.
C++17 introduces an overload for the latter, that returns a non-constant pointer (reference, which I am not sure if it's updated completely w.r.t. C++17):
const CharT* data() const; (1)
CharT* data(); (2) (since C++17)
c_str()
does only return a constant pointer:
const CharT* c_str() const;
Why the differentiation of these two methods in C++17, especially when C++11 was the one that made them homogeneous? In other words, why only the one method got an overload, while the other didn't?
The new overload was added by P0272R1 for C++17. Neither the paper itself nor the links therein discuss why only
data
was given new overloads butc_str
was not. We can only speculate at this point (unless people involved in the discussion chime in), but I'd like to offer the following points for consideration:Even just adding the overload to
data
broke some code; keeping this change conservative was a way to minimize negative impact.The
c_str
function had so far been entirely identical todata
and is effectively a "legacy" facility for interfacing code that takes "C string", i.e. an immutable, null-terminated char array. Since you can always replacec_str
bydata
, there's no particular reason to add to this legacy interface.I realize that the very motivation for P0292R1 was that there do exist legacy APIs that erroneously or for C reasons take only mutable pointers even though they don't mutate. All the same, I suppose we don't want to add more to string's already massive API that absolutely necessary.
One more point: as of C++17 you are now allowed to write to the null terminator, as long as you write the value zero. (Previously, it used to be UB to write anything to the null terminator.) A mutable
c_str
would create yet another entry point into this particular subtlety, and the fewer subtleties we have, the better.