This isn't a design question, really, though it may seem like it. (Well, okay, it's kind of a design question). What I'm wondering is why the C++ std::fstream
classes don't take a std::string
in their constructor or open methods. Everyone loves code examples so:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string filename = "testfile";
std::ifstream fin;
fin.open(filename.c_str()); // Works just fine.
fin.close();
//fin.open(filename); // Error: no such method.
//fin.close();
}
This gets me all the time when working with files. Surely the C++ library would use std::string
wherever possible?
There is no functionality difference between string and std::string because they're the same type.
C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.
The std::string type is the main string datatype in standard C++ since 1998, but it was not always part of C++. From C, C++ inherited the convention of using null-terminated strings that are handled by a pointer to their first element, and a library of functions that manipulate such strings.
A std::string's allocation is not guaranteed to be contiguous under the C++98/03 standard, but C++11 forces it to be. In practice, neither I nor Herb Sutter know of an implementation that does not use contiguous storage.
By taking a C string the C++03 std::fstream
class reduced dependency on the std::string
class. In C++11, however, the std::fstream
class does allow passing a std::string
for its constructor parameter.
Now, you may wonder why isn't there a transparent conversion from a std:string
to a C string, so a class that expects a C string could still take a std::string
just like a class that expects a std::string
can take a C string.
The reason is that this would cause a conversion cycle, which in turn may lead to problems. For example, suppose std::string
would be convertible to a C string so that you could use std::string
s with fstream
s. Suppose also that C string are convertible to std::string
s as is the state in the current standard. Now, consider the following:
void f(std::string str1, std::string str2);
void f(char* cstr1, char* cstr2);
void g()
{
char* cstr = "abc";
std::string str = "def";
f(cstr, str); // ERROR: ambiguous
}
Because you can convert either way between a std::string
and a C string the call to f()
could resolve to either of the two f()
alternatives, and is thus ambiguous. The solution is to break the conversion cycle by making one conversion direction explicit, which is what the STL chose to do with c_str()
.
There are several places where the C++ standard committee did not really optimize the interaction between facilities in the standard library.
std::string
and its use in the library is one of these.
One other example is std::swap
. Many containers have a swap member function, but no overload of std::swap is supplied. The same goes for std::sort
.
I hope all these small things will be fixed in the upcoming standard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With