Why don't the std::fstream classes take a std::string?
c++, file-io, stdstring, stl
Solution
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()`.
Problem
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?