Skip to content

Instantly share code, notes, and snippets.

@Snaipe
Last active September 20, 2015 20:35
Show Gist options
  • Save Snaipe/cc51a98fbc1ffb7af358 to your computer and use it in GitHub Desktop.
Save Snaipe/cc51a98fbc1ffb7af358 to your computer and use it in GitHub Desktop.
Inherited basic_fstream operator weirdness
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
template <typename CharT>
class my_basic_fstream : public std::basic_fstream<CharT> {
public:
my_basic_fstream(std::FILE *f) : std::basic_fstream<char>(f) {}
};
using my_fstream = my_basic_fstream<char>;
template <typename CharT>
struct get_file_stream_ {
static inline my_basic_fstream<CharT>& call(std::FILE* f) {
static std::unique_ptr<my_basic_fstream<CharT>> stream;
if (!stream)
stream.reset(new my_basic_fstream<CharT>(f));
return *stream;
}
};
static inline my_fstream& get_tmp_stream() {
return get_file_stream_<char>::call(std::tmpfile());
}
int main(void) {
my_fstream& f = get_tmp_stream();
f << "Foo";
f.seekg(0);
std::string written;
f >> written;
f.close();
if (written == "Foo")
std::cout << "All is well." << std::endl;
else
std::cout << "Expected \"Foo\", got \"" << written << "\"." << std::endl;
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#ifdef __GNUC__
# if defined(__MINGW32__) || defined(__MINGW64__)
# define off_t _off_t
# define off64_t _off64_t
# endif
# include <ext/stdio_sync_filebuf.h>
# if defined(__MINGW32__) || defined(__MINGW64__)
# undef off_t
# undef off64_t
# endif
#endif
template <typename CharT>
class my_basic_fstream : public std::basic_fstream<CharT> {
public:
my_basic_fstream(std::FILE* f)
#ifdef __GNUC__
: std::basic_fstream<CharT>()
, fbuf(new ::__gnu_cxx::stdio_sync_filebuf<CharT>(f))
#else
: std::basic_fstream<CharT>(f)
#endif
, file(f)
{
#ifdef __GNUC__
std::ios::rdbuf(&*fbuf);
#endif
}
my_basic_fstream(const my_basic_fstream& other) = delete;
my_basic_fstream& operator=(const my_basic_fstream& other) = delete;
my_basic_fstream(my_basic_fstream&& other) :
#ifdef __GNUC__
fbuf(std::move(other.fbuf)),
#endif
file(std::move(other.file))
{}
my_basic_fstream& operator=(my_basic_fstream&& other) {
#ifdef __GNUC__
fbuf = std::move(other.fbuf);
#endif
file = std::move(other.file);
}
void close(void) {
std::basic_fstream<CharT>::flush();
std::basic_fstream<CharT>::close();
std::fclose(file);
}
private:
#ifdef __GNUC__
std::shared_ptr<::__gnu_cxx::stdio_sync_filebuf<CharT>> fbuf;
#endif
std::FILE* file;
};
using my_fstream = my_basic_fstream<char>;
template <typename CharT>
struct get_file_stream_ {
static inline my_basic_fstream<CharT>& call(std::FILE* f) {
static std::unique_ptr<my_basic_fstream<CharT>> stream;
if (!stream)
stream.reset(new my_basic_fstream<CharT>(f));
return *stream;
}
};
static inline my_fstream& get_tmp_stream() {
return get_file_stream_<char>::call(std::tmpfile());
}
int main(void) {
my_fstream& f = get_tmp_stream();
f << "Foo";
f.seekg(0);
std::string written;
f >> written;
f.close();
if (written == "Foo")
std::cout << "All is well." << std::endl;
else
std::cout << "Expected \"Foo\", got \"" << written << "\"." << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment