This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Allow fstream ctor to take std::string arguments
- To: libstdc++ at gcc dot gnu dot org
- Subject: Allow fstream ctor to take std::string arguments
- From: Phil Edwards <pedwards at disaster dot jaj dot com>
- Date: Fri, 1 Jun 2001 15:28:55 -0400
This is just for the record; I won't propose applying this until post-3.0
even though it does nothing without the user's input. At one point I was
thinking of proposing this for 3.0, and for 3.1 leaving the extension /on/
by default, but that's prolly not smart now.
Friends, colleagues, and complete strangers often complain to me and
to the world in general (newsgroups) that you can't pass a string to an
fstream ctor; you have to use a char* to pass the filename. If you /were/
using a string to hold the filename -- as you should -- then you have to
use .c_str() to "drop down into C" briefly, as it were.
There are good reasons for not requiring std::string to be an argument and
they probably don't need to be repeated here. But comp.std.c++ has been
holding a wishlist-fest for the last few weeks, and some of the articles
I've moderated mention this "failing" of the I/O library, and hopes that
it can be "corrected" in C++0x.
Of course, we all know that it's good to see an actual implementation
of something, and how it gets used in the community, before adding that
something to the standard.
So, anyhow, I did this. A basic_string can be passed to the ctor as well
as open(). The string can be templated on a different character type than
the fstream. All of them are, by default, dropped by the preprocessor,
unless the user defines a hook before inclusion:
#define _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
#include <fstream>
which is cheesy but safe. Other methods solicited.
Including basic_string.h is probably quite a hit for parsing time; I didn't
measure. We could get away with including stringfwd.h (something which I
would like to see added to the standard) instead, if we were willing to move
the function bodies elsewhere (otherwise we need to see the decl of c_str()).
Built, tested, it works. I haven't run this past any of the language
experts I usually consult before posting :-) so it could probably stand
some improvement. Here was my simple test:
#include <iostream>
#define _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
#include <fstream>
int main()
{
std::string str = "c++config";
std::ifstream file (str);
file >> str;
// should print the initial "//" of c++config
std::cout << str << std::endl;
}
Phil
Index: std_fstream.h
===================================================================
RCS file: /home/pme/Repositories/GCC/gcc/libstdc++-v3/include/bits/std_fstream.h,v
retrieving revision 1.10
diff -u -3 -p -r1.10 std_fstream.h
--- std_fstream.h 2001/05/24 23:09:53 1.10
+++ std_fstream.h 2001/05/30 01:20:46
@@ -41,6 +41,9 @@
#include <bits/basic_file.h>
#include <bits/std_locale.h> // For codecvt
#include <bits/c++threads.h> // For __mutext_type
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+#include <bits/basic_string.h>
+#endif
namespace std
{
@@ -260,7 +263,19 @@ namespace std
this->init(&_M_filebuf);
this->open(__s, __mode);
}
-
+
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+ template <typename _StringCharT>
+ explicit
+ basic_ifstream(const basic_string<_StringCharT>& __s,
+ ios_base::openmode __mode = ios_base::in)
+ : __istream_type(NULL), _M_filebuf()
+ {
+ this->init(&_M_filebuf);
+ this->open(__s.c_str(), __mode);
+ }
+#endif
+
~basic_ifstream()
{ }
@@ -279,6 +294,17 @@ namespace std
this->setstate(ios_base::failbit);
}
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+ template <typename _StringCharT>
+ void
+ open(const basic_string<_StringCharT>& __s,
+ ios_base::openmode __mode = ios_base::in)
+ {
+ if (_M_filebuf.open(__s.c_str(), __mode | ios_base::in) == NULL)
+ this->setstate(ios_base::failbit);
+ }
+#endif
+
void
close(void)
{
@@ -322,6 +348,18 @@ namespace std
this->open(__s, __mode);
}
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+ template <typename _StringCharT>
+ explicit
+ basic_ofstream(const basic_string<_StringCharT>& __s,
+ ios_base::openmode __mode = ios_base::out|ios_base::trunc)
+ : __ostream_type(NULL), _M_filebuf()
+ {
+ this->init(&_M_filebuf);
+ this->open(__s.c_str(), __mode);
+ }
+#endif
+
~basic_ofstream()
{ }
@@ -341,6 +379,17 @@ namespace std
this->setstate(ios_base::failbit);
}
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+ template <typename _StringCharT>
+ void
+ open(const basic_string<_StringCharT>& __s,
+ ios_base::openmode __mode = ios_base::out | ios_base::trunc)
+ {
+ if (!_M_filebuf.open(__s.c_str(), __mode | ios_base::out))
+ this->setstate(ios_base::failbit);
+ }
+#endif
+
void
close(void)
{
@@ -385,6 +434,18 @@ namespace std
this->open(__s, __mode);
}
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+ template <typename _StringCharT>
+ explicit
+ basic_fstream(const basic_string<_StringCharT>& __s,
+ ios_base::openmode __mode = ios_base::in | ios_base::out)
+ : __iostream_type(NULL), _M_filebuf()
+ {
+ this->init(&_M_filebuf);
+ this->open(__s.c_str(), __mode);
+ }
+#endif
+
~basic_fstream()
{ }
@@ -403,6 +464,17 @@ namespace std
if (!_M_filebuf.open(__s, __mode))
setstate(ios_base::failbit);
}
+
+#ifdef _GLIBCPP_STRINGS_IN_IOSTREAM_CTORS
+ template <typename _StringCharT>
+ void
+ open(const basic_string<_StringCharT>& __s,
+ ios_base::openmode __mode = ios_base::in | ios_base::out)
+ {
+ if (!_M_filebuf.open(__s.c_str(), __mode))
+ this->setstate(ios_base::failbit);
+ }
+#endif
void
close(void)