Skip to content

static_assert fails in format-inl.h when using FMT_HEADER_ONLY with FMT_USE_LOCALE=0 #4550

@teruyamato0731

Description

@teruyamato0731

Hi,

I'm using {fmt} v12.0.0 with C++20 and have encountered a compilation issue when defining both FMT_HEADER_ONLY and FMT_USE_LOCALE=0.

The Problem

When these two macros are defined simultaneously, the compilation fails with a static_assert error in fmt/format-inl.h:69.

The error seems to be triggered by including <fmt/chrono.h>. It appears that some part of the chrono formatting functionality attempts to get a std::locale, but since FMT_USE_LOCALE=0 is active, fmt::locale is a dummy detail::locale type. This type mismatch causes the static_assert(std::is_same<Locale, locale>::value, ""); to fail.

Compilation Error Log:

In file included from /path/to/project/build/_deps/fmt-src/include/fmt/format.h:4375,
                 from /path/to/project/build/_deps/fmt-src/include/fmt/base.h:2992,
                 from /path/to/project/Core/App/app.cpp:3:
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h: In instantiation of 'Locale fmt::v12::locale_ref::get() const [with Locale = std::locale]':
/path/to/project/build/_deps/fmt-src/include/fmt/chrono.h:1598:65:   required from here
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h:69:47: error: static assertion failed
   69 |   static_assert(std::is_same<Locale, locale>::value, "");
      |                                               ^~~~~
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h:69:47: note: 'std::integral_constant<bool, false>::value' evaluates to false
/path/to/project/build/_deps/fmt-src/include/fmt/format-inl.h:73:10: error: could not convert 'fmt::v12::detail::locale()' from 'fmt::v12::detail::locale' to 'std::locale'
   73 |   return locale();
      |          ^~~~~~~~
      |          |
      |          fmt::v12::detail::locale
make[2]: *** [CMakeFiles/nucleo-g474re.dir/build.make:229: CMakeFiles/nucleo-g474re.dir/Core/App/app.cpp.obj] Error 1
make[1]: *** [CMakeFiles/Makefile2:119: CMakeFiles/nucleo-g474re-dokata.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

Related ODR Violation Warning

As a related issue, if I do not define FMT_HEADER_ONLY but still define FMT_USE_LOCALE=0 in my application code (while the {fmt} library itself is likely compiled with default settings), I receive ODR (One Definition Rule) violation warnings.

This is because the layout of locale_ref and context changes based on FMT_USE_LOCALE, leading to inconsistencies between translation units.

Warning Log:

/path/to/project/build/_deps/fmt-src/include/fmt/base.h:912:7: warning: type 'struct locale_ref' violates the C++ One Definition Rule [-Wodr]
  912 | class locale_ref {
      |       ^
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:912:7: note: a different type is defined in another translation unit
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:915:15: note: the first difference of corresponding definitions is field 'locale_'
  915 |   const void* locale_;  // A type-erased pointer to std::locale.
      |               ^
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:2668:7: warning: type 'struct context' violates the C++ One Definition Rule [-Wodr]
 2668 | class context {
      |       ^
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:2668:7: note: a different type is defined in another translation unit
/path/to/project/build/_deps/fmt-src/include/fmt/base.h:2672:36: note: the first difference of corresponding definitions is field 'loc_'
 2672 |   FMT_NO_UNIQUE_ADDRESS locale_ref loc_;
      |                                    ^

It seems the combination of FMT_HEADER_ONLY and FMT_USE_LOCALE=0 is not fully compatible, especially when headers like <fmt/chrono.h> are used. Is this an intended limitation, or a bug?

Thank you

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions