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
I believe that this has been thought about and was done to avoid the dependency; i.e. #include <fstream> should not force one to #include <string>.
To be honest, this seems like quite an inconsequential issue. A better question would be, why is std::string's interface so large?
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.
The stream IO library has been added to the standard C++ library before the STL. In order to not break backward compatibility, it has been decided to avoid modifying the IO library when the STL was added, even if that meant some issues like the one you raise.
Is there any class in STL that takes a string... I dont think so (couldnt find any in my quick search). So it's probably some design decision, that no class in STL should be dependent on any other STL class (that is not directly needed for functionality).
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()
.
Nowadays you can solve this problem very easily: add -std=c++11
to your CFLAGS
.