Don’t let ADL pick to_string_view (#4938)
- Don’t let ADL pick to_string_view
02bf4d1c disabled ADL for to_string_view by qualifying the is_string trait, and has_to_string_view and char_t are qualified for the same reason. Two call sites were left behind: value’s string constructor and the write() overload for types with a string view conversion. Both sit inside fmt::detail, where an unqualified call adds the argument’s own namespace to the overload set.
That splits the two halves of one decision. Both call sites are reached only through has_to_string_view or char_t, which are defined by the qualified expression, so ADL can never be needed to satisfy them - it can only add candidates the gate never considered. When the argument’s namespace declares a to_string_view template, the two tie during partial ordering and the call is ambiguous:
core.h(2211): error C2668: ‘to_string_view’: ambiguous call to overloaded function note: could be ‘string_view N::to_string_view(const T&)’ [found using argument-dependent lookup] note: or ‘basic_string_view fmt::detail::to_string_view<T,0>(const T&)’
Both are reachable. format(“{}”, x) stores the argument through value’s constructor; to_string(x) passes it to detail::write unmapped, which lands on the write() overload, as do FMT_COMPILE named fields and nested_formatter::write_arg. Reverting either line alone breaks the build of the test that covers it.
This turned up in Microsoft Office, which declares a constrained to_string_view template next to its own string types. It only breaks where those types are distinct classes, so the same code compiles on platforms whose string types are std aliases - the ADL set is namespace std there and picks up nothing.
One behaviour change worth noting: a non-template to_string_view in the argument’s namespace used to win outright at these call sites, so a type that satisfies is_std_string_like via find_first_of and data() but has no size() formatted through ADL and now fails to compile, because the trait only checks that the qualified overload is viable, not that its body instantiates. That is the removed extension point going away rather than a new restriction; ADL to_string_view stopped being supported in 02bf4d1c.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
{fmt} is an open-source formatting library providing a fast and safe alternative to C stdio and C++ iostreams.
Documentation
Cheat Sheets
Q&A: ask questions on StackOverflow with the tag fmt.
Try {fmt} in Compiler Explorer.
Features
(s)printf, iostreams,to_stringandto_chars, see Speed tests and Converting a hundred million integers to strings per secondcore.h,format.handformat-inl.h, and compiled code; see Compile time and code bloat-Wall -Wextra -pedanticFMT_HEADER_ONLYmacroSee the documentation for more details.
Examples
Print to stdout (run)
Format a string (run)
Format a string using positional arguments (run)
Print dates and times (run)
Output:
Print a container (run)
Output:
Check a format string at compile time
This gives a compile-time error in C++20 because
dis an invalid format specifier for a string.Write a file from a single thread
This can be up to 9 times faster than
fprintf.Print with colors and text styles
Output on a modern terminal with Unicode support:
Performance
{fmt} can be tens of percent to 20–30 times faster than
sprintfand iostreams, especially for numeric formatting. It minimizes dynamic memory allocations and can optionally compile format strings into efficient formatting code.See format-benchmark and dtoa-benchmark for benchmarks and methodology.
Time per double (smaller is better):
ostringstreamandsprintfare omitted because they are an order of magnitude slower than the other methods.Compile time and code bloat
The script bloat-test.py from format-benchmark measures the compile-time and code-size overhead each formatting method adds to application code. It generates 100 translation units and uses
printfor its alternative five times in each to simulate a medium-sized project. Library and module build costs are excluded. Results on an Apple M5 Max running macOS 26.6.2 with Apple Clang 21.0.0 (clang-2100.1.1.101), taking the best of three runs, are shown in the following tables.Optimized build (-O3)
Using modular {fmt} reduces optimized application-code compile time by 27% without changing the reported stripped binary size.
Non-optimized build
libc,libc++,libfmt, andlibfmt-modulewere linked as shared libraries to compare formatting function overhead only. Boost Format is header-only.Projects using {fmt}
Notable users include:
Find more projects using {fmt} on GitHub.