5

Those of us who have seen the beauty of STL try to use it as much as possible, and also encourage others to use it wherever we see them using raw pointers and arrays. Scott Meyers have written a whole book on STL, with title Effective STL. Yet what happened to the developers of ifstream that they preferred char* over std::string. I wonder why the first parameter of ifstream::open() is of type const char*, instead of const std::string &. Please have a look at it's signature:

void open(const char * filename, ios_base::openmode mode = ios_base::in );

Why this? Why not this:

void open(const string & filename, ios_base::openmode mode = ios_base::in );

Is this a serious mistake with the design? Or this design is deliberate? What could be the reason? I don't see any reason why they have preferred char* over std::string. Note we could still pass char* to the latter function that takes std::string. That's not a problem!

By the way, I'm aware that ifstream is a typedef, so no comment on my title.:P. It looks short that is why I used it.

The actual class template is :

template<class _Elem,class _Traits> class basic_ifstream;
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • The only thing streams have in common with the STL is that both are part of the std lib. __Standard library != STL.__ – sbi Jan 09 '11 at 19:14

3 Answers3

7

Because IOStream was designed way before part of the STL was integrated in the standard library. And the string class was made after that. It was pretty late in the standardization process and modifying IOStream was not considered save.

BTW, as part of the minor but convenient changes in C++0X is there was a clean up of this kind of things.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
4

My copy of the standard disagrees with you. It says both these are overloads:

void open(const char* s, ios_base::openmode mode = ios_base::in);
void open(const string& s, ios_base::openmode mode = ios_base::in);

However, that copy of the standard is a draft of the next version of the standard, C++0x.

The reason for this is that the iostreams library predates std::basic_string, and because the library designers didn't want someone to have to #include <string> and all it's other associated baggage if they didn't want to use it.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
0

It's typically no more expensive to get a C string from a std::string than it is to construct a std::string from a C string so, given that you are likely to want to use std::ifstream with filenames that come from both, using a const char* in the interface is not a significant cost.

Is this a serious mistake with the design?

What can't you do with the current interface? What concrete and significant benefit would taking a const std::string& in the interface yield?

The real benefit of a std::string overload, as I see it, is as a help to beginners making it easy to get things right when first attempting to use std::string and streams together. To experienced C++ developers the trivial cost of writing .c_str() when necessary is likely to be negligible compared to rest of the effort that goes into developing code.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • @Charles Bailey: that looks like post-facto rationalization. :P – Nawaz Jan 09 '11 at 17:09
  • @Nawaz: What are you asking for if not rationalization after the fact (given that the current interface has already been standardized)? – CB Bailey Jan 09 '11 at 17:11
  • @Charles Bailey: I mean, if they had preferred `std::string` over `char*`, you would have said the same thing. Just in reverse order. And it would still look rationale.:|... whereas my question was about why they themselves didn't use std::string if there is no harm in it. – Nawaz Jan 09 '11 at 17:14
  • Most implementations of STL strings have their internal buffer NULL-terminated all the time, so `c_str()` is a fast operation which simply returns the buffer pointer. – bdonlan Jan 09 '11 at 17:14
  • 1
    @bdonlan: yep, but `file.open("my very long file name path.txt")` invokes std::string construction which involves heap allocation. – Yakov Galka Jan 09 '11 at 17:16
  • 1
    To put it another way, if I was designing an interface now where a string was required as input (not arbitrary `char` data) and that string might come from a string literal, statically allocated or dynamically input, I would usually chose `const char*` over `const std::string&` and wouldn't bother with an overload. I don't think that it's bad design to have `const char*` in an interface, I believe it to be very slightly more flexible than requiring a `std::string` much as taking a `const shared_ptr&` is less flexible than `const X&`; it doesn't force a particular storage strategy. – CB Bailey Jan 09 '11 at 17:18