diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 641fd08bfae7..4435dd20b591 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -13,6 +13,8 @@ #if defined(_WIN32) && defined(__GLIBCXX__) # include # include +#elif defined(_WIN32) && defined(_LIBCPP_VERSION) +# include <__std_stream> #endif #include "format.h" @@ -55,35 +57,25 @@ struct is_streamable< (std::is_convertible::value && !std::is_enum::value)>> : std::false_type {}; -template FILE* get_file(std::basic_filebuf&) { - return nullptr; -} - -struct dummy_filebuf { - FILE* _Myfile; -}; -template struct ms_filebuf { - using type = dummy_filebuf; -}; -template struct ms_filebuf { - using type = T; -}; -using filebuf_type = ms_filebuf::type; - -FILE* get_file(filebuf_type& buf); - // Generate a unique explicit instantion in every translation unit using a tag // type in an anonymous namespace. namespace { -struct filebuf_access_tag {}; +struct file_access_tag {}; } // namespace -template -class filebuf_access { - friend FILE* get_file(filebuf_type& buf) { return buf.*file; } +template +class file_access { + friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; } }; -template class filebuf_access; + +#if FMT_MSC_VERSION +template class file_access; +auto get_file(std::filebuf&) -> FILE*; +#elif defined(_WIN32) && defined(_LIBCPP_VERSION) +template class file_access, + &std::__stdoutbuf::__file_>; +auto get_file(std::__stdoutbuf&) -> FILE*; +#endif inline bool write_ostream_unicode(std::ostream& os, fmt::string_view data) { #if FMT_MSC_VERSION @@ -99,6 +91,9 @@ inline bool write_ostream_unicode(std::ostream& os, fmt::string_view data) { else return false; if (c_file) return write_console(c_file, data); +#elif defined(_WIN32) && defined(_LIBCPP_VERSION) + if (auto* buf = dynamic_cast*>(os.rdbuf())) + if (FILE* f = get_file(*buf)) return write_console(f, data); #else ignore_unused(os); ignore_unused(data);