Skip to content

[libc++] Granularize <locale> #146650

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

philnik777
Copy link
Contributor

No description provided.

Copy link

github-actions bot commented Jul 2, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 force-pushed the granularize_locale branch 4 times, most recently from ce03942 to 3075fff Compare July 2, 2025 13:59
@philnik777 philnik777 marked this pull request as ready for review July 2, 2025 14:00
@philnik777 philnik777 requested a review from a team as a code owner July 2, 2025 14:00
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 2, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

Patch is 280.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/146650.diff

29 Files Affected:

  • (modified) libcxx/include/CMakeLists.txt (+9)
  • (modified) libcxx/include/__chrono/formatter.h (+3-1)
  • (modified) libcxx/include/__filesystem/path.h (-1)
  • (modified) libcxx/include/__filesystem/u8path.h (+1-6)
  • (added) libcxx/include/__locale_dir/check_grouping.h (+31)
  • (added) libcxx/include/__locale_dir/get_c_locale.h (+40)
  • (added) libcxx/include/__locale_dir/messages.h (+143)
  • (added) libcxx/include/__locale_dir/money.h (+873)
  • (added) libcxx/include/__locale_dir/num.h (+1072)
  • (added) libcxx/include/__locale_dir/scan_keyword.h (+143)
  • (added) libcxx/include/__locale_dir/time.h (+767)
  • (added) libcxx/include/__locale_dir/wbuffer_convert.h (+430)
  • (added) libcxx/include/__locale_dir/wstring_convert.h (+254)
  • (modified) libcxx/include/__ostream/basic_ostream.h (+3-1)
  • (modified) libcxx/include/__ostream/print.h (+1-1)
  • (modified) libcxx/include/__thread/thread.h (-1)
  • (modified) libcxx/include/experimental/iterator (+4)
  • (modified) libcxx/include/iomanip (+8-1)
  • (modified) libcxx/include/istream (+6-1)
  • (modified) libcxx/include/locale (+6-3477)
  • (modified) libcxx/include/module.modulemap.in (+10-1)
  • (modified) libcxx/include/ostream (+4)
  • (modified) libcxx/include/sstream (+1-1)
  • (modified) libcxx/test/libcxx/localization/locale.categories/__scan_keyword.pass.cpp (+2-1)
  • (modified) libcxx/test/libcxx/transitive_includes/cxx26.csv (-18)
  • (modified) libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp (+2-1)
  • (modified) libcxx/test/std/input.output/iostream.format/ext.manip/get_time.pass.cpp (+2-1)
  • (modified) libcxx/test/support/concat_macros.h (+1)
  • (modified) libcxx/test/tools/clang_tidy_checks/header_exportable_declarations.cpp (+2)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index c334b25574305..e2e3905777339 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -511,13 +511,19 @@ set(files
   __iterator/unreachable_sentinel.h
   __iterator/wrap_iter.h
   __locale
+  __locale_dir/check_grouping.h
+  __locale_dir/get_c_locale.h
   __locale_dir/locale_base_api.h
   __locale_dir/locale_base_api/android.h
   __locale_dir/locale_base_api/bsd_locale_fallbacks.h
   __locale_dir/locale_base_api/ibm.h
   __locale_dir/locale_base_api/musl.h
   __locale_dir/locale_base_api/openbsd.h
+  __locale_dir/messages.h
+  __locale_dir/money.h
+  __locale_dir/num.h
   __locale_dir/pad_and_output.h
+  __locale_dir/scan_keyword.h
   __locale_dir/support/apple.h
   __locale_dir/support/bsd_like.h
   __locale_dir/support/freebsd.h
@@ -526,6 +532,9 @@ set(files
   __locale_dir/support/no_locale/characters.h
   __locale_dir/support/no_locale/strtonum.h
   __locale_dir/support/windows.h
+  __locale_dir/time.h
+  __locale_dir/wbuffer_convert.h
+  __locale_dir/wstring_convert.h
   __math/abs.h
   __math/copysign.h
   __math/error_functions.h
diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h
index 86b606d27847b..49758397f6185 100644
--- a/libcxx/include/__chrono/formatter.h
+++ b/libcxx/include/__chrono/formatter.h
@@ -50,12 +50,14 @@
 #  include <__format/formatter.h>
 #  include <__format/parser_std_format_spec.h>
 #  include <__format/write_escaped.h>
+#  include <__iterator/istreambuf_iterator.h>
+#  include <__iterator/ostreambuf_iterator.h>
+#  include <__locale_dir/time.h>
 #  include <__memory/addressof.h>
 #  include <__type_traits/is_specialization.h>
 #  include <cmath>
 #  include <ctime>
 #  include <limits>
-#  include <locale>
 #  include <sstream>
 #  include <string_view>
 
diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h
index a2c28bfd79bb9..381e5678a5855 100644
--- a/libcxx/include/__filesystem/path.h
+++ b/libcxx/include/__filesystem/path.h
@@ -29,7 +29,6 @@
 
 #if _LIBCPP_HAS_LOCALIZATION
 #  include <iomanip> // for quoted
-#  include <locale>
 #endif
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/include/__filesystem/u8path.h b/libcxx/include/__filesystem/u8path.h
index e13980298d9e9..a701425e42919 100644
--- a/libcxx/include/__filesystem/u8path.h
+++ b/libcxx/include/__filesystem/u8path.h
@@ -13,14 +13,9 @@
 #include <__algorithm/unwrap_iter.h>
 #include <__config>
 #include <__filesystem/path.h>
+#include <__locale>
 #include <string>
 
-// Only required on Windows for __widen_from_utf8, and included conservatively
-// because it requires support for localization.
-#if defined(_LIBCPP_WIN32API)
-#  include <locale>
-#endif
-
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif
diff --git a/libcxx/include/__locale_dir/check_grouping.h b/libcxx/include/__locale_dir/check_grouping.h
new file mode 100644
index 0000000000000..93e9e404bb5f3
--- /dev/null
+++ b/libcxx/include/__locale_dir/check_grouping.h
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H
+#define _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H
+
+#include <__config>
+#include <__fwd/string.h>
+#include <ios>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+_LIBCPP_EXPORTED_FROM_ABI void
+__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err);
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_LOCALIZATION
+
+#endif // _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H
diff --git a/libcxx/include/__locale_dir/get_c_locale.h b/libcxx/include/__locale_dir/get_c_locale.h
new file mode 100644
index 0000000000000..e8bac9a87095b
--- /dev/null
+++ b/libcxx/include/__locale_dir/get_c_locale.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H
+#define _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H
+
+#include <__config>
+#include <__locale_dir/locale_base_api.h>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// FIXME: This should really be part of the locale base API
+
+#  if defined(__APPLE__) || defined(__FreeBSD__)
+#    define _LIBCPP_GET_C_LOCALE 0
+#  elif defined(__NetBSD__)
+#    define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
+#  else
+#    define _LIBCPP_GET_C_LOCALE __cloc()
+// Get the C locale object
+_LIBCPP_EXPORTED_FROM_ABI __locale::__locale_t __cloc();
+#    define __cloc_defined
+#  endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_LOCALIZATION
+
+#endif // _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H
diff --git a/libcxx/include/__locale_dir/messages.h b/libcxx/include/__locale_dir/messages.h
new file mode 100644
index 0000000000000..b2b394d59ed69
--- /dev/null
+++ b/libcxx/include/__locale_dir/messages.h
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOCALE_DIR_MESSAGES_H
+#define _LIBCPP___LOCALE_DIR_MESSAGES_H
+
+#include <__config>
+#include <__iterator/back_insert_iterator.h>
+#include <__locale>
+#include <string>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+class _LIBCPP_EXPORTED_FROM_ABI messages_base {
+public:
+  typedef intptr_t catalog;
+
+  _LIBCPP_HIDE_FROM_ABI messages_base() {}
+};
+
+template <class _CharT>
+class messages : public locale::facet, public messages_base {
+public:
+  typedef _CharT char_type;
+  typedef basic_string<_CharT> string_type;
+
+  _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {}
+
+  _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string<char>& __nm, const locale& __loc) const {
+    return do_open(__nm, __loc);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const {
+    return do_get(__c, __set, __msgid, __dflt);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); }
+
+  static locale::id id;
+
+protected:
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {}
+
+  virtual catalog do_open(const basic_string<char>&, const locale&) const;
+  virtual string_type do_get(catalog, int __set, int __msgid, const string_type& __dflt) const;
+  virtual void do_close(catalog) const;
+};
+
+template <class _CharT>
+locale::id messages<_CharT>::id;
+
+#    if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+// Most unix variants have catopen.  These are the specific ones that don't.
+#      if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__)
+#        define _LIBCPP_HAS_CATOPEN 1
+#        include <nl_types.h>
+#      else
+#        define _LIBCPP_HAS_CATOPEN 0
+#      endif
+#    else
+#      define _LIBCPP_HAS_CATOPEN 0
+#    endif
+
+template <class _CharT>
+typename messages<_CharT>::catalog messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const {
+#    if _LIBCPP_HAS_CATOPEN
+  return (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
+#    else  // !_LIBCPP_HAS_CATOPEN
+  (void)__nm;
+  return -1;
+#    endif // _LIBCPP_HAS_CATOPEN
+}
+
+template <class _CharT>
+typename messages<_CharT>::string_type
+messages<_CharT>::do_get(catalog __c, int __set, int __msgid, const string_type& __dflt) const {
+#    if _LIBCPP_HAS_CATOPEN
+  string __ndflt;
+  __narrow_to_utf8<sizeof(char_type) * __CHAR_BIT__>()(
+      std::back_inserter(__ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size());
+  nl_catd __cat = (nl_catd)__c;
+  static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type");
+  char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
+  string_type __w;
+  __widen_from_utf8<sizeof(char_type) * __CHAR_BIT__>()(std::back_inserter(__w), __n, __n + std::strlen(__n));
+  return __w;
+#    else  // !_LIBCPP_HAS_CATOPEN
+  (void)__c;
+  (void)__set;
+  (void)__msgid;
+  return __dflt;
+#    endif // _LIBCPP_HAS_CATOPEN
+}
+
+template <class _CharT>
+void messages<_CharT>::do_close(catalog __c) const {
+#    if _LIBCPP_HAS_CATOPEN
+  catclose((nl_catd)__c);
+#    else  // !_LIBCPP_HAS_CATOPEN
+  (void)__c;
+#    endif // _LIBCPP_HAS_CATOPEN
+}
+
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>;
+#    if _LIBCPP_HAS_WIDE_CHARACTERS
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>;
+#    endif
+
+template <class _CharT>
+class messages_byname : public messages<_CharT> {
+public:
+  typedef messages_base::catalog catalog;
+  typedef basic_string<_CharT> string_type;
+
+  _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {}
+
+  _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {}
+
+protected:
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {}
+};
+
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>;
+#    if _LIBCPP_HAS_WIDE_CHARACTERS
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>;
+#    endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_HAS_LOCALIZATION
+
+#endif // _LIBCPP___LOCALE_DIR_MESSAGES_H
diff --git a/libcxx/include/__locale_dir/money.h b/libcxx/include/__locale_dir/money.h
new file mode 100644
index 0000000000000..479a4edd36476
--- /dev/null
+++ b/libcxx/include/__locale_dir/money.h
@@ -0,0 +1,873 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___LOCALE_DIR_MONEY_H
+#define _LIBCPP___LOCALE_DIR_MONEY_H
+
+#include <__algorithm/copy.h>
+#include <__algorithm/equal.h>
+#include <__algorithm/find.h>
+#include <__algorithm/reverse.h>
+#include <__config>
+#include <__locale>
+#include <__locale_dir/check_grouping.h>
+#include <__locale_dir/get_c_locale.h>
+#include <__locale_dir/pad_and_output.h>
+#include <__memory/unique_ptr.h>
+#include <ios>
+#include <string>
+
+#if _LIBCPP_HAS_LOCALIZATION
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_PUSH_MACROS
+#  include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// money_base
+
+class _LIBCPP_EXPORTED_FROM_ABI money_base {
+public:
+  enum part { none, space, symbol, sign, value };
+  struct pattern {
+    char field[4];
+  };
+
+  _LIBCPP_HIDE_FROM_ABI money_base() {}
+};
+
+// moneypunct
+
+template <class _CharT, bool _International = false>
+class moneypunct : public locale::facet, public money_base {
+public:
+  typedef _CharT char_type;
+  typedef basic_string<char_type> string_type;
+
+  _LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {}
+
+  _LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }
+  _LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }
+  _LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }
+  _LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); }
+  _LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); }
+  _LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); }
+  _LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); }
+  _LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); }
+  _LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); }
+
+  static locale::id id;
+  static const bool intl = _International;
+
+protected:
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {}
+
+  virtual char_type do_decimal_point() const { return numeric_limits<char_type>::max(); }
+  virtual char_type do_thousands_sep() const { return numeric_limits<char_type>::max(); }
+  virtual string do_grouping() const { return string(); }
+  virtual string_type do_curr_symbol() const { return string_type(); }
+  virtual string_type do_positive_sign() const { return string_type(); }
+  virtual string_type do_negative_sign() const { return string_type(1, '-'); }
+  virtual int do_frac_digits() const { return 0; }
+  virtual pattern do_pos_format() const {
+    pattern __p = {{symbol, sign, none, value}};
+    return __p;
+  }
+  virtual pattern do_neg_format() const {
+    pattern __p = {{symbol, sign, none, value}};
+    return __p;
+  }
+};
+
+template <class _CharT, bool _International>
+locale::id moneypunct<_CharT, _International>::id;
+
+template <class _CharT, bool _International>
+const bool moneypunct<_CharT, _International>::intl;
+
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>;
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>;
+#    if _LIBCPP_HAS_WIDE_CHARACTERS
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>;
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>;
+#    endif
+
+// moneypunct_byname
+
+template <class _CharT, bool _International = false>
+class moneypunct_byname : public moneypunct<_CharT, _International> {
+public:
+  typedef money_base::pattern pattern;
+  typedef _CharT char_type;
+  typedef basic_string<char_type> string_type;
+
+  _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
+      : moneypunct<_CharT, _International>(__refs) {
+    init(__nm);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
+      : moneypunct<_CharT, _International>(__refs) {
+    init(__nm.c_str());
+  }
+
+protected:
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {}
+
+  char_type do_decimal_point() const override { return __decimal_point_; }
+  char_type do_thousands_sep() const override { return __thousands_sep_; }
+  string do_grouping() const override { return __grouping_; }
+  string_type do_curr_symbol() const override { return __curr_symbol_; }
+  string_type do_positive_sign() const override { return __positive_sign_; }
+  string_type do_negative_sign() const override { return __negative_sign_; }
+  int do_frac_digits() const override { return __frac_digits_; }
+  pattern do_pos_format() const override { return __pos_format_; }
+  pattern do_neg_format() const override { return __neg_format_; }
+
+private:
+  char_type __decimal_point_;
+  char_type __thousands_sep_;
+  string __grouping_;
+  string_type __curr_symbol_;
+  string_type __positive_sign_;
+  string_type __negative_sign_;
+  int __frac_digits_;
+  pattern __pos_format_;
+  pattern __neg_format_;
+
+  void init(const char*);
+};
+
+template <>
+_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, false>::init(const char*);
+template <>
+_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, true>::init(const char*);
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>;
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>;
+
+#    if _LIBCPP_HAS_WIDE_CHARACTERS
+template <>
+_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, false>::init(const char*);
+template <>
+_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, true>::init(const char*);
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>;
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>;
+#    endif
+
+// money_get
+
+template <class _CharT>
+class __money_get {
+protected:
+  typedef _CharT char_type;
+  typedef basic_string<char_type> string_type;
+
+  _LIBCPP_HIDE_FROM_ABI __money_get() {}
+
+  static void __gather_info(
+      bool __intl,
+      const locale& __loc,
+      money_base::pattern& __pat,
+      char_type& __dp,
+      char_type& __ts,
+      string& __grp,
+      string_type& __sym,
+      string_type& __psn,
+      string_type& __nsn,
+      int& __fd);
+};
+
+template <class _CharT>
+void __money_get<_CharT>::__gather_info(
+    bool __intl,
+    const locale& __loc,
+    money_base::pattern& __pat,
+    char_type& __dp,
+    char_type& __ts,
+    string& __grp,
+    string_type& __sym,
+    string_type& __psn,
+    string_type& __nsn,
+    int& __fd) {
+  if (__intl) {
+    const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);
+    __pat                                   = __mp.neg_format();
+    __nsn                                   = __mp.negative_sign();
+    __psn                                   = __mp.positive_sign();
+    __dp                                    = __mp.decimal_point();
+    __ts                                    = __mp.thousands_sep();
+    __grp                                   = __mp.grouping();
+    __sym                                   = __mp.curr_symbol();
+    __fd                                    = __mp.frac_digits();
+  } else {
+    const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);
+    __pat                                    = __mp.neg_format();
+    __nsn                                    = __mp.negative_sign();
+    __psn                                    = __mp.positive_sign();
+    __dp                                     = __mp.decimal_point();
+    __ts                                     = __mp.thousands_sep();
+    __grp                                    = __mp.grouping();
+    __sym                                    = __mp.curr_symbol();
+    __fd                                     = __mp.frac_digits();
+  }
+}
+
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>;
+#    if _LIBCPP_HAS_WIDE_CHARACTERS
+extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>;
+#    endif
+
+template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
+class money_get : public locale::facet, private __money_get<_CharT> {
+public:
+  typedef _CharT char_type;
+  typedef _InputIterator iter_type;
+  typedef basic_string<char_type> string_type;
+
+  _LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {}
+
+  _LIBCPP_HIDE_FROM_ABI iter_type
+  get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
+    return do_get(__b, __e, __intl, __iob, __err, __v);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI iter_type
+  get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {
+    return do_get(__b, __e, __intl, __iob, __err, __v);
+  }
+
+  static locale::id id;
+
+protected:
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {}
+
+  virtual iter_type
+  do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const;
+  virtual iter_type
+  do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const;
+
+private:
+  static bool __do_ge...
[truncated]

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with some comments, thanks for the cleanup.

As discussed, we should do the same for <__locale>.

@philnik777 philnik777 force-pushed the granularize_locale branch 3 times, most recently from 5c2382f to abc1c61 Compare July 3, 2025 12:43
@philnik777 philnik777 force-pushed the granularize_locale branch from abc1c61 to b15c37e Compare July 4, 2025 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants