diff --git a/stl/inc/format b/stl/inc/format index 105307688f5..f509e1903ad 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3824,18 +3824,20 @@ _EXPORT_STD using format_args = basic_format_args; _EXPORT_STD using wformat_args = basic_format_args; _EXPORT_STD template -_NODISCARD auto make_format_args(_Args&&... _Vals) { - static_assert((_Formattable_with, _Context> && ...), +_NODISCARD auto make_format_args(_Args&... _Vals) { + // TRANSITION, should cite the new working draft + static_assert((_Formattable_with, _Context> && ...), "Cannot format an argument. To make type T formattable, provide a formatter specialization. " - "See N4950 [format.arg.store]/2 and [formatter.requirements]."); + "See N4964 [format.arg.store]/2 (along with modification in P2905R2) and [formatter.requirements]."); return _Format_arg_store<_Context, _Args...>{_Vals...}; } _EXPORT_STD template -_NODISCARD auto make_wformat_args(_Args&&... _Vals) { - static_assert((_Formattable_with, wformat_context> && ...), +_NODISCARD auto make_wformat_args(_Args&... _Vals) { + // TRANSITION, should cite the new working draft + static_assert((_Formattable_with, wformat_context> && ...), "Cannot format an argument. To make type T formattable, provide a formatter specialization. " - "See N4950 [format.arg.store]/2 and [formatter.requirements]."); + "See N4964 [format.arg.store]/2 (along with modification in P2905R2) and [formatter.requirements]."); return _Format_arg_store{_Vals...}; } diff --git a/stl/inc/ostream b/stl/inc/ostream index de3b0a0feef..362a4722693 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -1245,10 +1245,10 @@ void _Print_impl(const _Add_newline _Add_nl, ostream& _Ostr, const format_string if constexpr (_Has_format_args) { if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { _STD _Vprint_unicode_impl( - _Add_nl, _Ostr, _Fmt.get(), _STD make_format_args(_STD forward<_Types>(_Args)...)); + _Add_nl, _Ostr, _Fmt.get(), _STD make_format_args(_Args...)); } else { _STD _Vprint_nonunicode_impl( - _Add_nl, _Ostr, _Fmt.get(), _STD make_format_args(_STD forward<_Types>(_Args)...)); + _Add_nl, _Ostr, _Fmt.get(), _STD make_format_args(_Args...)); } } else { const string _Unescaped_str{_Unescape_braces(_Add_nl, _Fmt.get())}; diff --git a/stl/inc/print b/stl/inc/print index 0e4c090925b..4d4c782f417 100644 --- a/stl/inc/print +++ b/stl/inc/print @@ -102,10 +102,10 @@ void _Print_impl( if constexpr (_Has_format_args) { if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { _STD _Vprint_unicode_impl( - _Add_nl, _Stream, _Fmt.get(), _STD make_format_args(_STD forward<_Types>(_Args)...)); + _Add_nl, _Stream, _Fmt.get(), _STD make_format_args(_Args...)); } else { _STD _Vprint_nonunicode_impl( - _Add_nl, _Stream, _Fmt.get(), _STD make_format_args(_STD forward<_Types>(_Args)...)); + _Add_nl, _Stream, _Fmt.get(), _STD make_format_args(_Args...)); } } else { const string _Unescaped_str{_Unescape_braces(_Add_nl, _Fmt.get())}; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 1c494ad1100..6a06f98c525 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -306,6 +306,7 @@ // P2711R1 Making Multi-Param Constructors Of Views explicit // P2736R2 Referencing The Unicode Standard // P2770R0 Stashing Stashing Iterators For Proper Flattening +// P2905R2 Runtime Format Strings // _HAS_CXX20 indirectly controls: // P0619R4 Removing C++17-Deprecated Features diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 17635616851..7288e398c65 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -189,6 +189,16 @@ std/ranges/range.adaptors/range.join.view/sentinel/eq.pass.cpp FAIL std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp FAIL std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp FAIL +# libc++ doesn't implement P2905R2 "Runtime Format Strings" +std/utilities/format/format.arguments/format.arg.store/make_format_args.pass.cpp FAIL +std/utilities/format/format.arguments/format.arg.store/make_format_args.sh.cpp FAIL +std/utilities/format/format.arguments/format.arg.store/make_wformat_args.pass.cpp FAIL +std/utilities/format/format.arguments/format.args/ctor.pass.cpp FAIL +std/utilities/format/format.formatter/format.context/format.context/arg.pass.cpp FAIL +std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp FAIL +std/utilities/format/format.formatter/format.context/format.context/locale.pass.cpp FAIL +std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp FAIL + # *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX *** # Tracked by VSO-593630 " Enable libcxx filesystem tests" diff --git a/tests/std/include/test_format_support.hpp b/tests/std/include/test_format_support.hpp index c8b2a218f45..60ee59410c3 100644 --- a/tests/std/include/test_format_support.hpp +++ b/tests/std/include/test_format_support.hpp @@ -161,9 +161,9 @@ struct VFormatFn { template [[nodiscard]] auto operator()(const std::basic_string_view str, Args&&... args) const { if constexpr (std::same_as) { - return std::vformat(str, std::make_format_args(std::forward(args)...)); + return std::vformat(str, std::make_format_args(args...)); } else { - return std::vformat(str, std::make_wformat_args(std::forward(args)...)); + return std::vformat(str, std::make_wformat_args(args...)); } } }; diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp index bf0baaa112b..c897dd00be0 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_formatting/test.cpp @@ -215,9 +215,9 @@ bool test_parse_chrono_format_specs() { template auto make_testing_format_args(Args&&... vals) { if constexpr (is_same_v) { - return make_wformat_args(forward(vals)...); + return make_wformat_args(vals...); } else { - return make_format_args(forward(vals)...); + return make_format_args(vals...); } } diff --git a/tests/std/tests/P0645R10_text_formatting_args/test.cpp b/tests/std/tests/P0645R10_text_formatting_args/test.cpp index 24ceead553d..8ce7e762fe4 100644 --- a/tests/std/tests/P0645R10_text_formatting_args/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_args/test.cpp @@ -248,7 +248,8 @@ void test_visit_monostate() { template void test_lwg3810() { - [[maybe_unused]] auto args_store = make_format_args(1, 2, 3); + int args[]{1, 2, 3}; + [[maybe_unused]] auto args_store = make_format_args(args[0], args[1], args[2]); static_assert(same_as>); } @@ -264,6 +265,32 @@ void test_lvalue_only_visitation() { visit_format_arg(lvalue_only_visitor{}, basic_format_arg{}); } +template +concept CanMakeFormatArgs = requires(Args&&... args) { make_format_args(static_cast(args)...); }; + +// P2905R2 Runtime format strings (make make_(w)format_args only take lvalue references) +template +void test_lvalue_reference_parameters() { // COMPILE-ONLY + using char_type = Context::char_type; + + static_assert(CanMakeFormatArgs&, basic_string_view&>); + static_assert( + CanMakeFormatArgs&, const basic_string_view&>); + + static_assert(CanMakeFormatArgs, const basic_string_view>); + + static_assert(!CanMakeFormatArgs); + static_assert(!CanMakeFormatArgs); + static_assert(!CanMakeFormatArgs); + static_assert(!CanMakeFormatArgs); + static_assert(!CanMakeFormatArgs); + static_assert(!CanMakeFormatArgs>); + static_assert(!CanMakeFormatArgs>); +} + int main() { test_basic_format_arg(); test_basic_format_arg(); @@ -277,4 +304,7 @@ int main() { test_lvalue_only_visitation(); test_lvalue_only_visitation(); + + test_lvalue_reference_parameters(); + test_lvalue_reference_parameters(); } diff --git a/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp index 928ff8aa893..4693ae2608f 100644 --- a/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_custom_formatting/test.cpp @@ -17,9 +17,9 @@ using namespace std; template auto make_testing_format_args(Args&&... vals) { if constexpr (is_same_v) { - return make_wformat_args(forward(vals)...); + return make_wformat_args(vals...); } else { - return make_format_args(forward(vals)...); + return make_format_args(vals...); } } diff --git a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp index 9954c85d776..c009a0c0024 100644 --- a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp @@ -65,9 +65,9 @@ using alternative_basic_string = basic_string auto make_testing_format_args(Args&&... vals) { if constexpr (is_same_v) { - return make_wformat_args(forward(vals)...); + return make_wformat_args(vals...); } else { - return make_format_args(forward(vals)...); + return make_format_args(vals...); } } diff --git a/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp b/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp index db01cedbefa..c11d20e7519 100644 --- a/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_utf8/test.cpp @@ -23,7 +23,8 @@ void test_multibyte_format_strings() { { try { // Bad fill character encoding: missing lead byte before \x9f - (void) vformat("{:\x9f\x8f\x88<10}"sv, make_format_args(42)); + int arg = 42; + (void) vformat("{:\x9f\x8f\x88<10}"sv, make_format_args(arg)); assert(false); } catch (const format_error&) { } diff --git a/tests/std/tests/P2286R8_text_formatting_escaping/test.cpp b/tests/std/tests/P2286R8_text_formatting_escaping/test.cpp index c735ff84dac..33288777a53 100644 --- a/tests/std/tests/P2286R8_text_formatting_escaping/test.cpp +++ b/tests/std/tests/P2286R8_text_formatting_escaping/test.cpp @@ -24,9 +24,9 @@ template template auto make_testing_format_args(Args&&... vals) { if constexpr (is_same_v) { - return make_wformat_args(forward(vals)...); + return make_wformat_args(vals...); } else { - return make_format_args(forward(vals)...); + return make_format_args(vals...); } }