From 367b2e2ec75163bf79a6886adcf02547a7fc31dc Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Tue, 11 Oct 2022 20:00:59 +0300 Subject: [PATCH] Explicitly export buffer for MSVC Some MSVC-specific behavior: Class ostream by inheriting detail::buffer implicitly exports it when fmt is built as a shared library. Unless os.h is included, the compiler assumes detail::buffer is not externally exported and instantiets a local copy of it, which cases ODR violation. --- include/fmt/core.h | 8 ++++++++ src/format.cc | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/include/fmt/core.h b/include/fmt/core.h index 5f44a974..4feb385f 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -960,6 +960,14 @@ template class buffer { } }; +#if defined(FMT_MSC_VERSION) +# ifdef FMT_EXPORT +extern template class buffer; +# else +template class FMT_API buffer; +# endif +#endif + struct buffer_traits { explicit buffer_traits(size_t) {} auto count() const -> size_t { return 0; } diff --git a/src/format.cc b/src/format.cc index 19dff444..03fc3321 100644 --- a/src/format.cc +++ b/src/format.cc @@ -22,6 +22,13 @@ template FMT_API auto locale_ref::get() const -> std::locale; // Explicit instantiations for char. +#if defined(FMT_MSC_VERSION) +// ostream does it implicitly, so we need make it explicitly +// otherwise we get ODR violation when {fmt} is built as a shared library +// and fmt/os.h is not included by the user +template class FMT_API buffer; +#endif + template FMT_API auto thousands_sep_impl(locale_ref) -> thousands_sep_result; template FMT_API auto decimal_point_impl(locale_ref) -> char;