//===----------------------------------------------------------------------===// // 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 TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H #define TEST_STD_UTILITIES_FORMAT_FORMAT_FUNCTIONS_FORMAT_TESTS_H #include #include #include #include #include #include #include #include "make_string.h" #include "string_literal.h" #include "test_macros.h" // In this file the following template types are used: // TestFunction must be callable as check(expected-result, string-to-format, args-to-format...) // ExceptionTest must be callable as check_exception(expected-exception, string-to-format, args-to-format...) #define STR(S) MAKE_STRING(CharT, S) #define SV(S) MAKE_STRING_VIEW(CharT, S) #define CSTR(S) MAKE_CSTRING(CharT, S) template struct context {}; template <> struct context { using type = std::format_context; }; #ifndef TEST_HAS_NO_WIDE_CHARACTERS template <> struct context { using type = std::wformat_context; }; #endif template using context_t = typename context::type; // A user-defined type used to test the handle formatter. enum class status : uint16_t { foo = 0xAAAA, bar = 0x5555, foobar = 0xAA55 }; // The formatter for a user-defined type used to test the handle formatter. template struct std::formatter { int type = 0; constexpr auto parse(basic_format_parse_context& parse_ctx) -> decltype(parse_ctx.begin()) { auto begin = parse_ctx.begin(); auto end = parse_ctx.end(); if (begin == end) return begin; switch (*begin) { case CharT('x'): break; case CharT('X'): type = 1; break; case CharT('s'): type = 2; break; case CharT('}'): return begin; default: throw_format_error("The format-spec type has a type not supported for a status argument"); } ++begin; if (begin != end && *begin != CharT('}')) throw_format_error("The format-spec should consume the input or end with a '}'"); return begin; } template auto format(status s, basic_format_context& ctx) -> decltype(ctx.out()) { const char* names[] = {"foo", "bar", "foobar"}; char buffer[6]; const char* begin; const char* end; switch (type) { case 0: begin = buffer; buffer[0] = '0'; buffer[1] = 'x'; end = std::to_chars(&buffer[2], std::end(buffer), static_cast(s), 16).ptr; break; case 1: begin = buffer; buffer[0] = '0'; buffer[1] = 'X'; end = std::to_chars(&buffer[2], std::end(buffer), static_cast(s), 16).ptr; std::transform(static_cast(&buffer[2]), end, &buffer[2], [](char c) { return std::toupper(c); }); break; case 2: switch (s) { case status::foo: begin = names[0]; break; case status::bar: begin = names[1]; break; case status::foobar: begin = names[2]; break; } end = begin + strlen(begin); break; } return std::copy(begin, end, ctx.out()); } private: void throw_format_error(const char* s) { #ifndef TEST_HAS_NO_EXCEPTIONS throw std::format_error(s); #else (void)s; std::abort(); #endif } }; template std::vector> invalid_types(std::string valid) { std::vector> result; #define CASE(T) \ case #T[0]: \ result.push_back(SV("Invalid formatter type {:" #T "}")); \ break; for (auto type : "aAbBcdeEfFgGopsxX") { if (valid.find(type) != std::string::npos) continue; switch (type) { CASE(a) CASE(A) CASE(b) CASE(B) CASE(c) CASE(d) CASE(e) CASE(E) CASE(f) CASE(F) CASE(g) CASE(G) CASE(o) CASE(p) CASE(s) CASE(x) CASE(X) case 0: break; default: assert(false && "Add the type to the list of cases."); } } #undef CASE return result; } // Using a const ref for world and universe so a string literal will be a character array. // When passed as character array W and U have different types. template void format_test_string(const W& world, const U& universe, TestFunction check, ExceptionTest check_exception) { // *** Valid input tests *** // Unsed argument is ignored. TODO FMT what does the Standard mandate? check.template operator()<"hello {}">(SV("hello world"), world, universe); check.template operator()<"hello {} and {}">(SV("hello world and universe"), world, universe); check.template operator()<"hello {0}">(SV("hello world"), world, universe); check.template operator()<"hello {1}">(SV("hello universe"), world, universe); check.template operator()<"hello {1} and {0}">(SV("hello universe and world"), world, universe); check.template operator()<"hello {:_>}">(SV("hello world"), world); check.template operator()<"hello {:>8}">(SV("hello world"), world); check.template operator()<"hello {:_>8}">(SV("hello ___world"), world); check.template operator()<"hello {:_^8}">(SV("hello _world__"), world); check.template operator()<"hello {:_<8}">(SV("hello world___"), world); check.template operator()<"hello {:>>8}">(SV("hello >>>world"), world); check.template operator()<"hello {:<>8}">(SV("hello <<8}">(SV("hello ^^^world"), world); check.template operator()<"hello {:$>{}}">(SV("hello $world"), world, 6); check.template operator()<"hello {0:$>{1}}">(SV("hello $world"), world, 6); check.template operator()<"hello {1:$>{0}}">(SV("hello $world"), 6, world); check.template operator()<"hello {:.5}">(SV("hello world"), world); check.template operator()<"hello {:.5}">(SV("hello unive"), universe); check.template operator()<"hello {:.{}}">(SV("hello univer"), universe, 6); check.template operator()<"hello {0:.{1}}">(SV("hello univer"), universe, 6); check.template operator()<"hello {1:.{0}}">(SV("hello univer"), 6, universe); check.template operator()<"hello {:%^7.7}">(SV("hello %world%"), world); check.template operator()<"hello {:%^7.7}">(SV("hello univers"), universe); check.template operator()<"hello {:%^{}.{}}">(SV("hello %world%"), world, 7, 7); check.template operator()<"hello {0:%^{1}.{2}}">(SV("hello %world%"), world, 7, 7); check.template operator()<"hello {0:%^{2}.{1}}">(SV("hello %world%"), world, 7, 7); check.template operator()<"hello {1:%^{0}.{2}}">(SV("hello %world%"), 7, world, 7); check.template operator()<"hello {:_>s}">(SV("hello world"), world); check.template operator()<"hello {:$>{}s}">(SV("hello $world"), world, 6); check.template operator()<"hello {:.5s}">(SV("hello world"), world); check.template operator()<"hello {:.{}s}">(SV("hello univer"), universe, 6); check.template operator()<"hello {:%^7.7s}">(SV("hello %world%"), world); check.template operator()<"hello {:#>8.3s}">(SV("hello #####uni"), universe); check.template operator()<"hello {:#^8.3s}">(SV("hello ##uni###"), universe); check.template operator()<"hello {:#<8.3s}">(SV("hello uni#####"), universe); // *** sign *** check_exception("The format-spec should consume the input or end with a '}'", SV("hello {:-}"), world); // *** alternate form *** check_exception("The format-spec should consume the input or end with a '}'", SV("hello {:#}"), world); // *** zero-padding *** check_exception("A format-spec width field shouldn't have a leading zero", SV("hello {:0}"), world); // *** width *** #ifdef _LIBCPP_VERSION // This limit isn't specified in the Standard. static_assert(std::__format::__number_max == 2'147'483'647, "Update the assert and the test."); check_exception("The numeric value of the format-spec is too large", SV("{:2147483648}"), world); check_exception("The numeric value of the format-spec is too large", SV("{:5000000000}"), world); check_exception("The numeric value of the format-spec is too large", SV("{:10000000000}"), world); #endif check_exception("A format-spec width field replacement should have a positive value", SV("hello {:{}}"), world, 0); check_exception("A format-spec arg-id replacement shouldn't have a negative value", SV("hello {:{}}"), world, -1); check_exception("A format-spec arg-id replacement exceeds the maximum supported value", SV("hello {:{}}"), world, unsigned(-1)); check_exception("Argument index out of bounds", SV("hello {:{}}"), world); check_exception("A format-spec arg-id replacement argument isn't an integral type", SV("hello {:{}}"), world, universe); check_exception("Using manual argument numbering in automatic argument numbering mode", SV("hello {:{0}}"), world, 1); check_exception("Using automatic argument numbering in manual argument numbering mode", SV("hello {0:{}}"), world, 1); // Arg-id may not have leading zeros. check_exception("Invalid arg-id", SV("hello {0:{01}}"), world, 1); // *** precision *** #ifdef _LIBCPP_VERSION // This limit isn't specified in the Standard. static_assert(std::__format::__number_max == 2'147'483'647, "Update the assert and the test."); check_exception("The numeric value of the format-spec is too large", SV("{:.2147483648}"), world); check_exception("The numeric value of the format-spec is too large", SV("{:.5000000000}"), world); check_exception("The numeric value of the format-spec is too large", SV("{:.10000000000}"), world); #endif // Precision 0 allowed, but not useful for string arguments. check.template operator()<"hello {:.{}}">(SV("hello "), world, 0); // Precision may have leading zeros. Secondly tests the value is still base 10. check.template operator()<"hello {:.000010}">(SV("hello 0123456789"), STR("0123456789abcdef")); check_exception("A format-spec arg-id replacement shouldn't have a negative value", SV("hello {:.{}}"), world, -1); check_exception("A format-spec arg-id replacement exceeds the maximum supported value", SV("hello {:.{}}"), world, ~0u); check_exception("Argument index out of bounds", SV("hello {:.{}}"), world); check_exception("A format-spec arg-id replacement argument isn't an integral type", SV("hello {:.{}}"), world, universe); check_exception("Using manual argument numbering in automatic argument numbering mode", SV("hello {:.{0}}"), world, 1); check_exception("Using automatic argument numbering in manual argument numbering mode", SV("hello {0:.{}}"), world, 1); // Arg-id may not have leading zeros. check_exception("Invalid arg-id", SV("hello {0:.{01}}"), world, 1); // *** locale-specific form *** check_exception("The format-spec should consume the input or end with a '}'", SV("hello {:L}"), world); // *** type *** for (const auto& fmt : invalid_types("s")) check_exception("The format-spec type has a type not supported for a string argument", fmt, world); } template void format_test_string_unicode(TestFunction check) { (void)check; #ifndef TEST_HAS_NO_UNICODE // Make sure all possible types are tested. For clarity don't use macros. if constexpr (std::same_as) { const char* c_string = "aßc"; check.template operator()<"{:*^5}">(SV("*aßc*"), c_string); check.template operator()<"{:*^4.2}">(SV("*aß*"), c_string); check.template operator()<"{:*^5}">(SV("*aßc*"), const_cast(c_string)); check.template operator()<"{:*^4.2}">(SV("*aß*"), const_cast(c_string)); check.template operator()<"{:*^5}">(SV("*aßc*"), "aßc"); check.template operator()<"{:*^4.2}">(SV("*aß*"), "aßc"); check.template operator()<"{:*^5}">(SV("*aßc*"), std::string("aßc")); check.template operator()<"{:*^4.2}">(SV("*aß*"), std::string("aßc")); check.template operator()<"{:*^5}">(SV("*aßc*"), std::string_view("aßc")); check.template operator()<"{:*^4.2}">(SV("*aß*"), std::string_view("aßc")); } # ifndef TEST_HAS_NO_WIDE_CHARACTERS else { const wchar_t* c_string = L"aßc"; check.template operator()<"{:*^5}">(SV("*aßc*"), c_string); check.template operator()<"{:*^4.2}">(SV("*aß*"), c_string); check.template operator()<"{:*^5}">(SV("*aßc*"), const_cast(c_string)); check.template operator()<"{:*^4.2}">(SV("*aß*"), const_cast(c_string)); check.template operator()<"{:*^5}">(SV("*aßc*"), L"aßc"); check.template operator()<"{:*^4.2}">(SV("*aß*"), L"aßc"); check.template operator()<"{:*^5}">(SV("*aßc*"), std::wstring(L"aßc")); check.template operator()<"{:*^4.2}">(SV("*aß*"), std::wstring(L"aßc")); check.template operator()<"{:*^5}">(SV("*aßc*"), std::wstring_view(L"aßc")); check.template operator()<"{:*^4.2}">(SV("*aß*"), std::wstring_view(L"aßc")); } # endif // ß requires one column check.template operator()<"{}">(SV("aßc"), STR("aßc")); check.template operator()<"{:.3}">(SV("aßc"), STR("aßc")); check.template operator()<"{:.2}">(SV("aß"), STR("aßc")); check.template operator()<"{:.1}">(SV("a"), STR("aßc")); check.template operator()<"{:3.3}">(SV("aßc"), STR("aßc")); check.template operator()<"{:2.2}">(SV("aß"), STR("aßc")); check.template operator()<"{:1.1}">(SV("a"), STR("aßc")); check.template operator()<"{:-<6}">(SV("aßc---"), STR("aßc")); check.template operator()<"{:-^6}">(SV("-aßc--"), STR("aßc")); check.template operator()<"{:->6}">(SV("---aßc"), STR("aßc")); // \u1000 requires two columns check.template operator()<"{}">(SV("a\u1110c"), STR("a\u1110c")); check.template operator()<"{:.4}">(SV("a\u1100c"), STR("a\u1100c")); check.template operator()<"{:.3}">(SV("a\u1100"), STR("a\u1100c")); check.template operator()<"{:.2}">(SV("a"), STR("a\u1100c")); check.template operator()<"{:.1}">(SV("a"), STR("a\u1100c")); check.template operator()<"{:-<4.4}">(SV("a\u1100c"), STR("a\u1100c")); check.template operator()<"{:-<3.3}">(SV("a\u1100"), STR("a\u1100c")); check.template operator()<"{:-<2.2}">(SV("a-"), STR("a\u1100c")); check.template operator()<"{:-<1.1}">(SV("a"), STR("a\u1100c")); check.template operator()<"{:-<7}">(SV("a\u1110c---"), STR("a\u1110c")); check.template operator()<"{:-^7}">(SV("-a\u1110c--"), STR("a\u1110c")); check.template operator()<"{:->7}">(SV("---a\u1110c"), STR("a\u1110c")); #endif // TEST_HAS_NO_UNICODE } template void format_string_tests(TestFunction check, ExceptionTest check_exception) { std::basic_string world = STR("world"); std::basic_string universe = STR("universe"); // Test a string literal in a way it won't decay to a pointer. if constexpr (std::same_as) format_test_string("world", "universe", check, check_exception); #ifndef TEST_HAS_NO_WIDE_CHARACTERS else format_test_string(L"world", L"universe", check, check_exception); #endif format_test_string(world.c_str(), universe.c_str(), check, check_exception); format_test_string(const_cast(world.c_str()), const_cast(universe.c_str()), check, check_exception); format_test_string(std::basic_string_view(world), std::basic_string_view(universe), check, check_exception); format_test_string(world, universe, check, check_exception); format_test_string_unicode(check); } template void format_test_bool(TestFunction check, ExceptionTest check_exception) { // *** align-fill & width *** check.template operator()<"answer is '{:7}'">(SV("answer is 'true '"), true); check.template operator()<"answer is '{:>7}'">(SV("answer is ' true'"), true); check.template operator()<"answer is '{:<7}'">(SV("answer is 'true '"), true); check.template operator()<"answer is '{:^7}'">(SV("answer is ' true '"), true); check.template operator()<"answer is '{:8s}'">(SV("answer is 'false '"), false); check.template operator()<"answer is '{:>8s}'">(SV("answer is ' false'"), false); check.template operator()<"answer is '{:<8s}'">(SV("answer is 'false '"), false); check.template operator()<"answer is '{:^8s}'">(SV("answer is ' false '"), false); check.template operator()<"answer is '{:->7}'">(SV("answer is '---true'"), true); check.template operator()<"answer is '{:-<7}'">(SV("answer is 'true---'"), true); check.template operator()<"answer is '{:-^7}'">(SV("answer is '-true--'"), true); check.template operator()<"answer is '{:->8s}'">(SV("answer is '---false'"), false); check.template operator()<"answer is '{:-<8s}'">(SV("answer is 'false---'"), false); check.template operator()<"answer is '{:-^8s}'">(SV("answer is '-false--'"), false); // *** Sign *** check_exception("A sign field isn't allowed in this format-spec", SV("{:-}"), true); check_exception("A sign field isn't allowed in this format-spec", SV("{:+}"), true); check_exception("A sign field isn't allowed in this format-spec", SV("{: }"), true); check_exception("A sign field isn't allowed in this format-spec", SV("{:-s}"), true); check_exception("A sign field isn't allowed in this format-spec", SV("{:+s}"), true); check_exception("A sign field isn't allowed in this format-spec", SV("{: s}"), true); // *** alternate form *** check_exception("An alternate form field isn't allowed in this format-spec", SV("{:#}"), true); check_exception("An alternate form field isn't allowed in this format-spec", SV("{:#s}"), true); // *** zero-padding *** check_exception("A zero-padding field isn't allowed in this format-spec", SV("{:0}"), true); check_exception("A zero-padding field isn't allowed in this format-spec", SV("{:0s}"), true); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.s}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0s}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42s}"), true); // *** locale-specific form *** // See locale-specific_form.pass.cpp // *** type *** for (const auto& fmt : invalid_types("bBdosxX")) check_exception("The format-spec type has a type not supported for a bool argument", fmt, true); } template void format_test_bool_as_integer(TestFunction check, ExceptionTest check_exception) { // *** align-fill & width *** check.template operator()<"answer is '{:<1d}'">(SV("answer is '1'"), true); check.template operator()<"answer is '{:<2d}'">(SV("answer is '1 '"), true); check.template operator()<"answer is '{:<2d}'">(SV("answer is '0 '"), false); check.template operator()<"answer is '{:6d}'">(SV("answer is ' 1'"), true); check.template operator()<"answer is '{:>6d}'">(SV("answer is ' 1'"), true); check.template operator()<"answer is '{:<6d}'">(SV("answer is '1 '"), true); check.template operator()<"answer is '{:^6d}'">(SV("answer is ' 1 '"), true); check.template operator()<"answer is '{:*>6d}'">(SV("answer is '*****0'"), false); check.template operator()<"answer is '{:*<6d}'">(SV("answer is '0*****'"), false); check.template operator()<"answer is '{:*^6d}'">(SV("answer is '**0***'"), false); // Test whether zero padding is ignored check.template operator()<"answer is '{:>06d}'">(SV("answer is ' 1'"), true); check.template operator()<"answer is '{:<06d}'">(SV("answer is '1 '"), true); check.template operator()<"answer is '{:^06d}'">(SV("answer is ' 1 '"), true); // *** Sign *** check.template operator()<"answer is {:d}">(SV("answer is 1"), true); check.template operator()<"answer is {:-d}">(SV("answer is 0"), false); check.template operator()<"answer is {:+d}">(SV("answer is +1"), true); check.template operator()<"answer is {: d}">(SV("answer is 0"), false); // *** alternate form *** check.template operator()<"answer is {:+#d}">(SV("answer is +1"), true); check.template operator()<"answer is {:+b}">(SV("answer is +1"), true); check.template operator()<"answer is {:+#b}">(SV("answer is +0b1"), true); check.template operator()<"answer is {:+#B}">(SV("answer is +0B1"), true); check.template operator()<"answer is {:+o}">(SV("answer is +1"), true); check.template operator()<"answer is {:+#o}">(SV("answer is +01"), true); check.template operator()<"answer is {:+x}">(SV("answer is +1"), true); check.template operator()<"answer is {:+#x}">(SV("answer is +0x1"), true); check.template operator()<"answer is {:+X}">(SV("answer is +1"), true); check.template operator()<"answer is {:+#X}">(SV("answer is +0X1"), true); check.template operator()<"answer is {:#d}">(SV("answer is 0"), false); check.template operator()<"answer is {:b}">(SV("answer is 0"), false); check.template operator()<"answer is {:#b}">(SV("answer is 0b0"), false); check.template operator()<"answer is {:#B}">(SV("answer is 0B0"), false); check.template operator()<"answer is {:o}">(SV("answer is 0"), false); check.template operator()<"answer is {:#o}">(SV("answer is 0"), false); check.template operator()<"answer is {:x}">(SV("answer is 0"), false); check.template operator()<"answer is {:#x}">(SV("answer is 0x0"), false); check.template operator()<"answer is {:X}">(SV("answer is 0"), false); check.template operator()<"answer is {:#X}">(SV("answer is 0X0"), false); // *** zero-padding & width *** check.template operator()<"answer is {:+#012d}">(SV("answer is +00000000001"), true); check.template operator()<"answer is {:+012b}">(SV("answer is +00000000001"), true); check.template operator()<"answer is {:+#012b}">(SV("answer is +0b000000001"), true); check.template operator()<"answer is {:+#012B}">(SV("answer is +0B000000001"), true); check.template operator()<"answer is {:+012o}">(SV("answer is +00000000001"), true); check.template operator()<"answer is {:+#012o}">(SV("answer is +00000000001"), true); check.template operator()<"answer is {:+012x}">(SV("answer is +00000000001"), true); check.template operator()<"answer is {:+#012x}">(SV("answer is +0x000000001"), true); check.template operator()<"answer is {:+012X}">(SV("answer is +00000000001"), true); check.template operator()<"answer is {:+#012X}">(SV("answer is +0X000000001"), true); check.template operator()<"answer is {:#012d}">(SV("answer is 000000000000"), false); check.template operator()<"answer is {:012b}">(SV("answer is 000000000000"), false); check.template operator()<"answer is {:#012b}">(SV("answer is 0b0000000000"), false); check.template operator()<"answer is {:#012B}">(SV("answer is 0B0000000000"), false); check.template operator()<"answer is {:012o}">(SV("answer is 000000000000"), false); check.template operator()<"answer is {:#012o}">(SV("answer is 000000000000"), false); check.template operator()<"answer is {:012x}">(SV("answer is 000000000000"), false); check.template operator()<"answer is {:#012x}">(SV("answer is 0x0000000000"), false); check.template operator()<"answer is {:012X}">(SV("answer is 000000000000"), false); check.template operator()<"answer is {:#012X}">(SV("answer is 0X0000000000"), false); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0}"), true); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42}"), true); // *** locale-specific form *** // See locale-specific_form.pass.cpp // *** type *** for (const auto& fmt : invalid_types("bBcdosxX")) check_exception("The format-spec type has a type not supported for a bool argument", fmt, true); } template void format_test_integer_as_integer(TestFunction check, ExceptionTest check_exception) { // *** align-fill & width *** check.template operator()<"answer is '{:<1}'">(SV("answer is '42'"), I(42)); check.template operator()<"answer is '{:<2}'">(SV("answer is '42'"), I(42)); check.template operator()<"answer is '{:<3}'">(SV("answer is '42 '"), I(42)); check.template operator()<"answer is '{:7}'">(SV("answer is ' 42'"), I(42)); check.template operator()<"answer is '{:>7}'">(SV("answer is ' 42'"), I(42)); check.template operator()<"answer is '{:<7}'">(SV("answer is '42 '"), I(42)); check.template operator()<"answer is '{:^7}'">(SV("answer is ' 42 '"), I(42)); check.template operator()<"answer is '{:*>7}'">(SV("answer is '*****42'"), I(42)); check.template operator()<"answer is '{:*<7}'">(SV("answer is '42*****'"), I(42)); check.template operator()<"answer is '{:*^7}'">(SV("answer is '**42***'"), I(42)); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07}'">(SV("answer is ' 42'"), I(42)); check.template operator()<"answer is '{:<07}'">(SV("answer is '42 '"), I(42)); check.template operator()<"answer is '{:^07}'">(SV("answer is ' 42 '"), I(42)); // *** Sign *** if constexpr (std::signed_integral) check.template operator()<"answer is {}">(SV("answer is -42"), I(-42)); check.template operator()<"answer is {}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {}">(SV("answer is 42"), I(42)); if constexpr (std::signed_integral) check.template operator()<"answer is {:-}">(SV("answer is -42"), I(-42)); check.template operator()<"answer is {:-}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:-}">(SV("answer is 42"), I(42)); if constexpr (std::signed_integral) check.template operator()<"answer is {:+}">(SV("answer is -42"), I(-42)); check.template operator()<"answer is {:+}">(SV("answer is +0"), I(0)); check.template operator()<"answer is {:+}">(SV("answer is +42"), I(42)); if constexpr (std::signed_integral) check.template operator()<"answer is {: }">(SV("answer is -42"), I(-42)); check.template operator()<"answer is {: }">(SV("answer is 0"), I(0)); check.template operator()<"answer is {: }">(SV("answer is 42"), I(42)); // *** alternate form *** if constexpr (std::signed_integral) { check.template operator()<"answer is {:#}">(SV("answer is -42"), I(-42)); check.template operator()<"answer is {:#d}">(SV("answer is -42"), I(-42)); check.template operator()<"answer is {:b}">(SV("answer is -101010"), I(-42)); check.template operator()<"answer is {:#b}">(SV("answer is -0b101010"), I(-42)); check.template operator()<"answer is {:#B}">(SV("answer is -0B101010"), I(-42)); check.template operator()<"answer is {:o}">(SV("answer is -52"), I(-42)); check.template operator()<"answer is {:#o}">(SV("answer is -052"), I(-42)); check.template operator()<"answer is {:x}">(SV("answer is -2a"), I(-42)); check.template operator()<"answer is {:#x}">(SV("answer is -0x2a"), I(-42)); check.template operator()<"answer is {:X}">(SV("answer is -2A"), I(-42)); check.template operator()<"answer is {:#X}">(SV("answer is -0X2A"), I(-42)); } check.template operator()<"answer is {:#}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:#d}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:b}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:#b}">(SV("answer is 0b0"), I(0)); check.template operator()<"answer is {:#B}">(SV("answer is 0B0"), I(0)); check.template operator()<"answer is {:o}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:#o}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:x}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:#x}">(SV("answer is 0x0"), I(0)); check.template operator()<"answer is {:X}">(SV("answer is 0"), I(0)); check.template operator()<"answer is {:#X}">(SV("answer is 0X0"), I(0)); check.template operator()<"answer is {:+#}">(SV("answer is +42"), I(42)); check.template operator()<"answer is {:+#d}">(SV("answer is +42"), I(42)); check.template operator()<"answer is {:+b}">(SV("answer is +101010"), I(42)); check.template operator()<"answer is {:+#b}">(SV("answer is +0b101010"), I(42)); check.template operator()<"answer is {:+#B}">(SV("answer is +0B101010"), I(42)); check.template operator()<"answer is {:+o}">(SV("answer is +52"), I(42)); check.template operator()<"answer is {:+#o}">(SV("answer is +052"), I(42)); check.template operator()<"answer is {:+x}">(SV("answer is +2a"), I(42)); check.template operator()<"answer is {:+#x}">(SV("answer is +0x2a"), I(42)); check.template operator()<"answer is {:+X}">(SV("answer is +2A"), I(42)); check.template operator()<"answer is {:+#X}">(SV("answer is +0X2A"), I(42)); // *** zero-padding & width *** if constexpr (std::signed_integral) { check.template operator()<"answer is {:#012}">(SV("answer is -00000000042"), I(-42)); check.template operator()<"answer is {:#012d}">(SV("answer is -00000000042"), I(-42)); check.template operator()<"answer is {:012b}">(SV("answer is -00000101010"), I(-42)); check.template operator()<"answer is {:#012b}">(SV("answer is -0b000101010"), I(-42)); check.template operator()<"answer is {:#012B}">(SV("answer is -0B000101010"), I(-42)); check.template operator()<"answer is {:012o}">(SV("answer is -00000000052"), I(-42)); check.template operator()<"answer is {:#012o}">(SV("answer is -00000000052"), I(-42)); check.template operator()<"answer is {:012x}">(SV("answer is -0000000002a"), I(-42)); check.template operator()<"answer is {:#012x}">(SV("answer is -0x00000002a"), I(-42)); check.template operator()<"answer is {:012X}">(SV("answer is -0000000002A"), I(-42)); check.template operator()<"answer is {:#012X}">(SV("answer is -0X00000002A"), I(-42)); } check.template operator()<"answer is {:#012}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:#012d}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:012b}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:#012b}">(SV("answer is 0b0000000000"), I(0)); check.template operator()<"answer is {:#012B}">(SV("answer is 0B0000000000"), I(0)); check.template operator()<"answer is {:012o}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:#012o}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:012x}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:#012x}">(SV("answer is 0x0000000000"), I(0)); check.template operator()<"answer is {:012X}">(SV("answer is 000000000000"), I(0)); check.template operator()<"answer is {:#012X}">(SV("answer is 0X0000000000"), I(0)); check.template operator()<"answer is {:+#012}">(SV("answer is +00000000042"), I(42)); check.template operator()<"answer is {:+#012d}">(SV("answer is +00000000042"), I(42)); check.template operator()<"answer is {:+012b}">(SV("answer is +00000101010"), I(42)); check.template operator()<"answer is {:+#012b}">(SV("answer is +0b000101010"), I(42)); check.template operator()<"answer is {:+#012B}">(SV("answer is +0B000101010"), I(42)); check.template operator()<"answer is {:+012o}">(SV("answer is +00000000052"), I(42)); check.template operator()<"answer is {:+#012o}">(SV("answer is +00000000052"), I(42)); check.template operator()<"answer is {:+012x}">(SV("answer is +0000000002a"), I(42)); check.template operator()<"answer is {:+#012x}">(SV("answer is +0x00000002a"), I(42)); check.template operator()<"answer is {:+012X}">(SV("answer is +0000000002A"), I(42)); check.template operator()<"answer is {:+#012X}">(SV("answer is +0X00000002A"), I(42)); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), I(0)); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0}"), I(0)); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42}"), I(0)); // *** locale-specific form *** // See locale-specific_form.pass.cpp // *** type *** for (const auto& fmt : invalid_types("bBcdoxX")) check_exception("The format-spec type has a type not supported for an integer argument", fmt, 42); } template void format_test_integer_as_char(TestFunction check, ExceptionTest check_exception) { // *** align-fill & width *** check.template operator()<"answer is '{:6c}'">(SV("answer is '* '"), I(42)); check.template operator()<"answer is '{:>6c}'">(SV("answer is ' *'"), I(42)); check.template operator()<"answer is '{:<6c}'">(SV("answer is '* '"), I(42)); check.template operator()<"answer is '{:^6c}'">(SV("answer is ' * '"), I(42)); check.template operator()<"answer is '{:->6c}'">(SV("answer is '-----*'"), I(42)); check.template operator()<"answer is '{:-<6c}'">(SV("answer is '*-----'"), I(42)); check.template operator()<"answer is '{:-^6c}'">(SV("answer is '--*---'"), I(42)); // *** Sign *** check.template operator()<"answer is {:c}">(SV("answer is *"), I(42)); check_exception("A sign field isn't allowed in this format-spec", SV("answer is {:-c}"), I(42)); check_exception("A sign field isn't allowed in this format-spec", SV("answer is {:+c}"), I(42)); check_exception("A sign field isn't allowed in this format-spec", SV("answer is {: c}"), I(42)); // *** alternate form *** check_exception("An alternate form field isn't allowed in this format-spec", SV("answer is {:#c}"), I(42)); // *** zero-padding & width *** check_exception("A zero-padding field isn't allowed in this format-spec", SV("answer is {:01c}"), I(42)); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.c}"), I(0)); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0c}"), I(0)); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42c}"), I(0)); // *** locale-specific form *** // Note it has no effect but it's allowed. check.template operator()<"answer is '{:Lc}'">(SV("answer is '*'"), I(42)); // *** type *** for (const auto& fmt : invalid_types("bBcdoxX")) check_exception("The format-spec type has a type not supported for an integer argument", fmt, I(42)); // *** Validate range *** // TODO FMT Update test after adding 128-bit support. if constexpr (sizeof(I) <= sizeof(long long)) { // The code has some duplications to keep the if statement readable. if constexpr (std::signed_integral) { if constexpr (std::signed_integral && sizeof(I) > sizeof(CharT)) { check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits::min()); check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits::max()); } else if constexpr (std::unsigned_integral && sizeof(I) >= sizeof(CharT)) { check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits::max()); } } else if constexpr (sizeof(I) > sizeof(CharT)) { check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits::max()); } } } template void format_test_integer(TestFunction check, ExceptionTest check_exception) { format_test_integer_as_integer(check, check_exception); format_test_integer_as_char(check, check_exception); } template void format_test_signed_integer(TestFunction check, ExceptionTest check_exception) { format_test_integer(check, check_exception); format_test_integer(check, check_exception); format_test_integer(check, check_exception); format_test_integer(check, check_exception); format_test_integer(check, check_exception); #ifndef TEST_HAS_NO_INT128 format_test_integer<__int128_t, CharT>(check, check_exception); #endif // *** check the minma and maxima *** check.template operator()<"{:#b}">(SV("-0b10000000"), std::numeric_limits::min()); check.template operator()<"{:#o}">(SV("-0200"), std::numeric_limits::min()); check.template operator()<"{:#}">(SV("-128"), std::numeric_limits::min()); check.template operator()<"{:#x}">(SV("-0x80"), std::numeric_limits::min()); check.template operator()<"{:#b}">(SV("-0b1000000000000000"), std::numeric_limits::min()); check.template operator()<"{:#o}">(SV("-0100000"), std::numeric_limits::min()); check.template operator()<"{:#}">(SV("-32768"), std::numeric_limits::min()); check.template operator()<"{:#x}">(SV("-0x8000"), std::numeric_limits::min()); check.template operator()<"{:#b}">(SV("-0b10000000000000000000000000000000"), std::numeric_limits::min()); check.template operator()<"{:#o}">(SV("-020000000000"), std::numeric_limits::min()); check.template operator()<"{:#}">(SV("-2147483648"), std::numeric_limits::min()); check.template operator()<"{:#x}">(SV("-0x80000000"), std::numeric_limits::min()); check.template operator()<"{:#b}">(SV("-0b1000000000000000000000000000000000000000000000000000000000000000"), std::numeric_limits::min()); check.template operator()<"{:#o}">(SV("-01000000000000000000000"), std::numeric_limits::min()); check.template operator()<"{:#}">(SV("-9223372036854775808"), std::numeric_limits::min()); check.template operator()<"{:#x}">(SV("-0x8000000000000000"), std::numeric_limits::min()); check.template operator()<"{:#b}">(SV("0b1111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("0177"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("127"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0x7f"), std::numeric_limits::max()); check.template operator()<"{:#b}">(SV("0b111111111111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("077777"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("32767"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0x7fff"), std::numeric_limits::max()); check.template operator()<"{:#b}">(SV("0b1111111111111111111111111111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("017777777777"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("2147483647"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0x7fffffff"), std::numeric_limits::max()); check.template operator()<"{:#b}">(SV("0b111111111111111111111111111111111111111111111111111111111111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("0777777777777777777777"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("9223372036854775807"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0x7fffffffffffffff"), std::numeric_limits::max()); // TODO FMT Add __int128_t test after implementing full range. } template void format_test_unsigned_integer(TestFunction check, ExceptionTest check_exception) { format_test_integer(check, check_exception); format_test_integer(check, check_exception); format_test_integer(check, check_exception); format_test_integer(check, check_exception); format_test_integer(check, check_exception); #ifndef TEST_HAS_NO_INT128 format_test_integer<__uint128_t, CharT>(check, check_exception); #endif // *** test the maxima *** check.template operator()<"{:#b}">(SV("0b11111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("0377"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("255"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0xff"), std::numeric_limits::max()); check.template operator()<"{:#b}">(SV("0b1111111111111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("0177777"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("65535"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0xffff"), std::numeric_limits::max()); check.template operator()<"{:#b}">(SV("0b11111111111111111111111111111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("037777777777"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("4294967295"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0xffffffff"), std::numeric_limits::max()); check.template operator()<"{:#b}">(SV("0b1111111111111111111111111111111111111111111111111111111111111111"), std::numeric_limits::max()); check.template operator()<"{:#o}">(SV("01777777777777777777777"), std::numeric_limits::max()); check.template operator()<"{:#}">(SV("18446744073709551615"), std::numeric_limits::max()); check.template operator()<"{:#x}">(SV("0xffffffffffffffff"), std::numeric_limits::max()); // TODO FMT Add __uint128_t test after implementing full range. } template void format_test_char(TestFunction check, ExceptionTest check_exception) { // ***** Char type ***** // *** align-fill & width *** check.template operator()<"answer is '{:6}'">(SV("answer is '* '"), CharT('*')); check.template operator()<"answer is '{:>6}'">(SV("answer is ' *'"), CharT('*')); check.template operator()<"answer is '{:<6}'">(SV("answer is '* '"), CharT('*')); check.template operator()<"answer is '{:^6}'">(SV("answer is ' * '"), CharT('*')); check.template operator()<"answer is '{:6c}'">(SV("answer is '* '"), CharT('*')); check.template operator()<"answer is '{:>6c}'">(SV("answer is ' *'"), CharT('*')); check.template operator()<"answer is '{:<6c}'">(SV("answer is '* '"), CharT('*')); check.template operator()<"answer is '{:^6c}'">(SV("answer is ' * '"), CharT('*')); check.template operator()<"answer is '{:->6}'">(SV("answer is '-----*'"), CharT('*')); check.template operator()<"answer is '{:-<6}'">(SV("answer is '*-----'"), CharT('*')); check.template operator()<"answer is '{:-^6}'">(SV("answer is '--*---'"), CharT('*')); check.template operator()<"answer is '{:->6c}'">(SV("answer is '-----*'"), CharT('*')); check.template operator()<"answer is '{:-<6c}'">(SV("answer is '*-----'"), CharT('*')); check.template operator()<"answer is '{:-^6c}'">(SV("answer is '--*---'"), CharT('*')); // *** Sign *** check_exception("A sign field isn't allowed in this format-spec", SV("{:-}"), CharT('*')); check_exception("A sign field isn't allowed in this format-spec", SV("{:+}"), CharT('*')); check_exception("A sign field isn't allowed in this format-spec", SV("{: }"), CharT('*')); check_exception("A sign field isn't allowed in this format-spec", SV("{:-c}"), CharT('*')); check_exception("A sign field isn't allowed in this format-spec", SV("{:+c}"), CharT('*')); check_exception("A sign field isn't allowed in this format-spec", SV("{: c}"), CharT('*')); // *** alternate form *** check_exception("An alternate form field isn't allowed in this format-spec", SV("{:#}"), CharT('*')); check_exception("An alternate form field isn't allowed in this format-spec", SV("{:#c}"), CharT('*')); // *** zero-padding *** check_exception("A zero-padding field isn't allowed in this format-spec", SV("{:0}"), CharT('*')); check_exception("A zero-padding field isn't allowed in this format-spec", SV("{:0c}"), CharT('*')); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.c}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0c}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42c}"), CharT('*')); // *** locale-specific form *** // Note it has no effect but it's allowed. check.template operator()<"answer is '{:L}'">(SV("answer is '*'"), '*'); check.template operator()<"answer is '{:Lc}'">(SV("answer is '*'"), '*'); // *** type *** for (const auto& fmt : invalid_types("bBcdoxX")) check_exception("The format-spec type has a type not supported for a char argument", fmt, CharT('*')); } template void format_test_char_as_integer(TestFunction check, ExceptionTest check_exception) { // *** align-fill & width *** check.template operator()<"answer is '{:<1d}'">(SV("answer is '42'"), CharT('*')); check.template operator()<"answer is '{:<2d}'">(SV("answer is '42'"), CharT('*')); check.template operator()<"answer is '{:<3d}'">(SV("answer is '42 '"), CharT('*')); check.template operator()<"answer is '{:7d}'">(SV("answer is ' 42'"), CharT('*')); check.template operator()<"answer is '{:>7d}'">(SV("answer is ' 42'"), CharT('*')); check.template operator()<"answer is '{:<7d}'">(SV("answer is '42 '"), CharT('*')); check.template operator()<"answer is '{:^7d}'">(SV("answer is ' 42 '"), CharT('*')); check.template operator()<"answer is '{:*>7d}'">(SV("answer is '*****42'"), CharT('*')); check.template operator()<"answer is '{:*<7d}'">(SV("answer is '42*****'"), CharT('*')); check.template operator()<"answer is '{:*^7d}'">(SV("answer is '**42***'"), CharT('*')); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07d}'">(SV("answer is ' 42'"), CharT('*')); check.template operator()<"answer is '{:<07d}'">(SV("answer is '42 '"), CharT('*')); check.template operator()<"answer is '{:^07d}'">(SV("answer is ' 42 '"), CharT('*')); // *** Sign *** check.template operator()<"answer is {:d}">(SV("answer is 42"), CharT('*')); check.template operator()<"answer is {:-d}">(SV("answer is 42"), CharT('*')); check.template operator()<"answer is {:+d}">(SV("answer is +42"), CharT('*')); check.template operator()<"answer is {: d}">(SV("answer is 42"), CharT('*')); // *** alternate form *** check.template operator()<"answer is {:+#d}">(SV("answer is +42"), CharT('*')); check.template operator()<"answer is {:+b}">(SV("answer is +101010"), CharT('*')); check.template operator()<"answer is {:+#b}">(SV("answer is +0b101010"), CharT('*')); check.template operator()<"answer is {:+#B}">(SV("answer is +0B101010"), CharT('*')); check.template operator()<"answer is {:+o}">(SV("answer is +52"), CharT('*')); check.template operator()<"answer is {:+#o}">(SV("answer is +052"), CharT('*')); check.template operator()<"answer is {:+x}">(SV("answer is +2a"), CharT('*')); check.template operator()<"answer is {:+#x}">(SV("answer is +0x2a"), CharT('*')); check.template operator()<"answer is {:+X}">(SV("answer is +2A"), CharT('*')); check.template operator()<"answer is {:+#X}">(SV("answer is +0X2A"), CharT('*')); // *** zero-padding & width *** check.template operator()<"answer is {:+#012d}">(SV("answer is +00000000042"), CharT('*')); check.template operator()<"answer is {:+012b}">(SV("answer is +00000101010"), CharT('*')); check.template operator()<"answer is {:+#012b}">(SV("answer is +0b000101010"), CharT('*')); check.template operator()<"answer is {:+#012B}">(SV("answer is +0B000101010"), CharT('*')); check.template operator()<"answer is {:+012o}">(SV("answer is +00000000052"), CharT('*')); check.template operator()<"answer is {:+#012o}">(SV("answer is +00000000052"), CharT('*')); check.template operator()<"answer is {:+012x}">(SV("answer is +0000000002a"), CharT('*')); check.template operator()<"answer is {:+#012x}">(SV("answer is +0x00000002a"), CharT('*')); check.template operator()<"answer is {:+012X}">(SV("answer is +0000000002A"), CharT('*')); check.template operator()<"answer is {:+#012X}">(SV("answer is +0X00000002A"), CharT('*')); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.d}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.0d}"), CharT('*')); check_exception("The format-spec should consume the input or end with a '}'", SV("{:.42d}"), CharT('*')); // *** locale-specific form *** // See locale-specific_form.pass.cpp // *** type *** for (const auto& fmt : invalid_types("bBcdoxX")) check_exception("The format-spec type has a type not supported for a char argument", fmt, '*'); } template void format_test_floating_point_hex_lower_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // Test whether the hexadecimal letters are the proper case. // The precision is too large for float, so two tests are used. check.template operator()<"answer is '{:a}'">(SV("answer is '1.abcp+0'"), F(0x1.abcp+0)); check.template operator()<"answer is '{:a}'">(SV("answer is '1.defp+0'"), F(0x1.defp+0)); // *** align-fill & width *** check.template operator()<"answer is '{:7a}'">(SV("answer is ' 1p-2'"), F(0.25)); check.template operator()<"answer is '{:>7a}'">(SV("answer is ' 1p-2'"), F(0.25)); check.template operator()<"answer is '{:<7a}'">(SV("answer is '1p-2 '"), F(0.25)); check.template operator()<"answer is '{:^7a}'">(SV("answer is ' 1p-2 '"), F(0.25)); check.template operator()<"answer is '{:->7a}'">(SV("answer is '---1p-3'"), F(125e-3)); check.template operator()<"answer is '{:-<7a}'">(SV("answer is '1p-3---'"), F(125e-3)); check.template operator()<"answer is '{:-^7a}'">(SV("answer is '-1p-3--'"), F(125e-3)); check.template operator()<"answer is '{:*>6a}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6a}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6a}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7a}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7a}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7a}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6a}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6a}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6a}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7a}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7a}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7a}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07a}'">(SV("answer is ' 1p-2'"), F(0.25)); check.template operator()<"answer is '{:<07a}'">(SV("answer is '1p-2 '"), F(0.25)); check.template operator()<"answer is '{:^07a}'">(SV("answer is ' 1p-2 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:a}'">(SV("answer is '0p+0'"), F(0)); check.template operator()<"answer is '{:-a}'">(SV("answer is '0p+0'"), F(0)); check.template operator()<"answer is '{:+a}'">(SV("answer is '+0p+0'"), F(0)); check.template operator()<"answer is '{: a}'">(SV("answer is ' 0p+0'"), F(0)); check.template operator()<"answer is '{:a}'">(SV("answer is '-0p+0'"), F(-0.)); check.template operator()<"answer is '{:-a}'">(SV("answer is '-0p+0'"), F(-0.)); check.template operator()<"answer is '{:+a}'">(SV("answer is '-0p+0'"), F(-0.)); check.template operator()<"answer is '{: a}'">(SV("answer is '-0p+0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:a}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-a}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+a}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:a}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-a}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+a}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:a}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-a}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+a}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: a}'">(SV("answer is '-nan'"), nan_neg); // *** alternate form *** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:a}'">(SV("answer is '0p+0'"), F(0)); check.template operator()<"answer is '{:#a}'">(SV("answer is '0.p+0'"), F(0)); check.template operator()<"answer is '{:.0a}'">(SV("answer is '1p+1'"), F(2.5)); check.template operator()<"answer is '{:#.0a}'">(SV("answer is '1.p+1'"), F(2.5)); check.template operator()<"answer is '{:#a}'">(SV("answer is '1.4p+1'"), F(2.5)); check.template operator()<"answer is '{:#a}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#a}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#a}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:04a}'">(SV("answer is '1p-5'"), 0.03125); check.template operator()<"answer is '{:+05a}'">(SV("answer is '+1p-5'"), 0.03125); check.template operator()<"answer is '{:+06a}'">(SV("answer is '+01p-5'"), 0.03125); check.template operator()<"answer is '{:07a}'">(SV("answer is '0001p-5'"), 0.03125); check.template operator()<"answer is '{:-07a}'">(SV("answer is '0001p-5'"), 0.03125); check.template operator()<"answer is '{:+07a}'">(SV("answer is '+001p-5'"), 0.03125); check.template operator()<"answer is '{: 07a}'">(SV("answer is ' 001p-5'"), 0.03125); check.template operator()<"answer is '{:010a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010a}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010a}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010a}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010a}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010a}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010a}'">(SV("answer is ' -nan'"), nan_neg); // *** precision *** // See format_test_floating_point_hex_lower_case_precision // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_hex_upper_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // Test whether the hexadecimal letters are the proper case. // The precision is too large for float, so two tests are used. check.template operator()<"answer is '{:A}'">(SV("answer is '1.ABCP+0'"), F(0x1.abcp+0)); check.template operator()<"answer is '{:A}'">(SV("answer is '1.DEFP+0'"), F(0x1.defp+0)); // *** align-fill & width *** check.template operator()<"answer is '{:7A}'">(SV("answer is ' 1P-2'"), F(0.25)); check.template operator()<"answer is '{:>7A}'">(SV("answer is ' 1P-2'"), F(0.25)); check.template operator()<"answer is '{:<7A}'">(SV("answer is '1P-2 '"), F(0.25)); check.template operator()<"answer is '{:^7A}'">(SV("answer is ' 1P-2 '"), F(0.25)); check.template operator()<"answer is '{:->7A}'">(SV("answer is '---1P-3'"), F(125e-3)); check.template operator()<"answer is '{:-<7A}'">(SV("answer is '1P-3---'"), F(125e-3)); check.template operator()<"answer is '{:-^7A}'">(SV("answer is '-1P-3--'"), F(125e-3)); check.template operator()<"answer is '{:*>6A}'">(SV("answer is '***INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6A}'">(SV("answer is 'INF***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6A}'">(SV("answer is '*INF**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7A}'">(SV("answer is '###-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7A}'">(SV("answer is '-INF###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7A}'">(SV("answer is '#-INF##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6A}'">(SV("answer is '^^^NAN'"), nan_pos); check.template operator()<"answer is '{:^<6A}'">(SV("answer is 'NAN^^^'"), nan_pos); check.template operator()<"answer is '{:^^6A}'">(SV("answer is '^NAN^^'"), nan_pos); check.template operator()<"answer is '{:0>7A}'">(SV("answer is '000-NAN'"), nan_neg); check.template operator()<"answer is '{:0<7A}'">(SV("answer is '-NAN000'"), nan_neg); check.template operator()<"answer is '{:0^7A}'">(SV("answer is '0-NAN00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07A}'">(SV("answer is ' 1P-2'"), F(0.25)); check.template operator()<"answer is '{:<07A}'">(SV("answer is '1P-2 '"), F(0.25)); check.template operator()<"answer is '{:^07A}'">(SV("answer is ' 1P-2 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:A}'">(SV("answer is '0P+0'"), F(0)); check.template operator()<"answer is '{:-A}'">(SV("answer is '0P+0'"), F(0)); check.template operator()<"answer is '{:+A}'">(SV("answer is '+0P+0'"), F(0)); check.template operator()<"answer is '{: A}'">(SV("answer is ' 0P+0'"), F(0)); check.template operator()<"answer is '{:A}'">(SV("answer is '-0P+0'"), F(-0.)); check.template operator()<"answer is '{:-A}'">(SV("answer is '-0P+0'"), F(-0.)); check.template operator()<"answer is '{:+A}'">(SV("answer is '-0P+0'"), F(-0.)); check.template operator()<"answer is '{: A}'">(SV("answer is '-0P+0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:A}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-A}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+A}'">(SV("answer is '+INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:A}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:-A}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:+A}'">(SV("answer is '+NAN'"), nan_pos); check.template operator()<"answer is '{: A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:A}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:-A}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:+A}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{: A}'">(SV("answer is '-NAN'"), nan_neg); // *** alternate form *** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:A}'">(SV("answer is '0P+0'"), F(0)); check.template operator()<"answer is '{:#A}'">(SV("answer is '0.P+0'"), F(0)); check.template operator()<"answer is '{:.0A}'">(SV("answer is '1P+1'"), F(2.5)); check.template operator()<"answer is '{:#.0A}'">(SV("answer is '1.P+1'"), F(2.5)); check.template operator()<"answer is '{:#A}'">(SV("answer is '1.4P+1'"), F(2.5)); check.template operator()<"answer is '{:#A}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#A}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:#A}'">(SV("answer is '-NAN'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:04A}'">(SV("answer is '1P-5'"), 0.03125); check.template operator()<"answer is '{:+05A}'">(SV("answer is '+1P-5'"), 0.03125); check.template operator()<"answer is '{:+06A}'">(SV("answer is '+01P-5'"), 0.03125); check.template operator()<"answer is '{:07A}'">(SV("answer is '0001P-5'"), 0.03125); check.template operator()<"answer is '{:-07A}'">(SV("answer is '0001P-5'"), 0.03125); check.template operator()<"answer is '{:+07A}'">(SV("answer is '+001P-5'"), 0.03125); check.template operator()<"answer is '{: 07A}'">(SV("answer is ' 001P-5'"), 0.03125); check.template operator()<"answer is '{:010A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010A}'">(SV("answer is ' +INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:-010A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:+010A}'">(SV("answer is ' +NAN'"), nan_pos); check.template operator()<"answer is '{: 010A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:010A}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:-010A}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:+010A}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{: 010A}'">(SV("answer is ' -NAN'"), nan_neg); // *** precision *** // See format_test_floating_point_hex_upper_case_precision // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_hex_lower_case_precision(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:14.6a}'">(SV("answer is ' 1.000000p-2'"), F(0.25)); check.template operator()<"answer is '{:>14.6a}'">(SV("answer is ' 1.000000p-2'"), F(0.25)); check.template operator()<"answer is '{:<14.6a}'">(SV("answer is '1.000000p-2 '"), F(0.25)); check.template operator()<"answer is '{:^14.6a}'">(SV("answer is ' 1.000000p-2 '"), F(0.25)); check.template operator()<"answer is '{:->14.6a}'">(SV("answer is '---1.000000p-3'"), F(125e-3)); check.template operator()<"answer is '{:-<14.6a}'">(SV("answer is '1.000000p-3---'"), F(125e-3)); check.template operator()<"answer is '{:-^14.6a}'">(SV("answer is '-1.000000p-3--'"), F(125e-3)); check.template operator()<"answer is '{:*>6.6a}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6.6a}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6.6a}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7.6a}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7.6a}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7.6a}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6.6a}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6.6a}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6.6a}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7.6a}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7.6a}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7.6a}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>014.6a}'">(SV("answer is ' 1.000000p-2'"), F(0.25)); check.template operator()<"answer is '{:<014.6a}'">(SV("answer is '1.000000p-2 '"), F(0.25)); check.template operator()<"answer is '{:^014.6a}'">(SV("answer is ' 1.000000p-2 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:.6a}'">(SV("answer is '0.000000p+0'"), F(0)); check.template operator()<"answer is '{:-.6a}'">(SV("answer is '0.000000p+0'"), F(0)); check.template operator()<"answer is '{:+.6a}'">(SV("answer is '+0.000000p+0'"), F(0)); check.template operator()<"answer is '{: .6a}'">(SV("answer is ' 0.000000p+0'"), F(0)); check.template operator()<"answer is '{:.6a}'">(SV("answer is '-0.000000p+0'"), F(-0.)); check.template operator()<"answer is '{:-.6a}'">(SV("answer is '-0.000000p+0'"), F(-0.)); check.template operator()<"answer is '{:+.6a}'">(SV("answer is '-0.000000p+0'"), F(-0.)); check.template operator()<"answer is '{: .6a}'">(SV("answer is '-0.000000p+0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:.6a}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-.6a}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+.6a}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: .6a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:.6a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-.6a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+.6a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: .6a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:.6a}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-.6a}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+.6a}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: .6a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:.6a}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-.6a}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+.6a}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: .6a}'">(SV("answer is '-nan'"), nan_neg); // *** alternate form *** check.template operator()<"answer is '{:#.6a}'">(SV("answer is '1.400000p+1'"), F(2.5)); check.template operator()<"answer is '{:#.6a}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#.6a}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#.6a}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#.6a}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:011.6a}'">(SV("answer is '1.000000p-5'"), 0.03125); check.template operator()<"answer is '{:+012.6a}'">(SV("answer is '+1.000000p-5'"), 0.03125); check.template operator()<"answer is '{:+013.6a}'">(SV("answer is '+01.000000p-5'"), 0.03125); check.template operator()<"answer is '{:014.6a}'">(SV("answer is '0001.000000p-5'"), 0.03125); check.template operator()<"answer is '{:-014.6a}'">(SV("answer is '0001.000000p-5'"), 0.03125); check.template operator()<"answer is '{:+014.6a}'">(SV("answer is '+001.000000p-5'"), 0.03125); check.template operator()<"answer is '{: 014.6a}'">(SV("answer is ' 001.000000p-5'"), 0.03125); check.template operator()<"answer is '{:010.6a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010.6a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010.6a}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010.6a}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010.6a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010.6a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010.6a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010.6a}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010.6a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010.6a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010.6a}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010.6a}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010.6a}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010.6a}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010.6a}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010.6a}'">(SV("answer is ' -nan'"), nan_neg); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_hex_upper_case_precision(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:14.6A}'">(SV("answer is ' 1.000000P-2'"), F(0.25)); check.template operator()<"answer is '{:>14.6A}'">(SV("answer is ' 1.000000P-2'"), F(0.25)); check.template operator()<"answer is '{:<14.6A}'">(SV("answer is '1.000000P-2 '"), F(0.25)); check.template operator()<"answer is '{:^14.6A}'">(SV("answer is ' 1.000000P-2 '"), F(0.25)); check.template operator()<"answer is '{:->14.6A}'">(SV("answer is '---1.000000P-3'"), F(125e-3)); check.template operator()<"answer is '{:-<14.6A}'">(SV("answer is '1.000000P-3---'"), F(125e-3)); check.template operator()<"answer is '{:-^14.6A}'">(SV("answer is '-1.000000P-3--'"), F(125e-3)); check.template operator()<"answer is '{:*>6.6A}'">(SV("answer is '***INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6.6A}'">(SV("answer is 'INF***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6.6A}'">(SV("answer is '*INF**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7.6A}'">(SV("answer is '###-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7.6A}'">(SV("answer is '-INF###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7.6A}'">(SV("answer is '#-INF##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6.6A}'">(SV("answer is '^^^NAN'"), nan_pos); check.template operator()<"answer is '{:^<6.6A}'">(SV("answer is 'NAN^^^'"), nan_pos); check.template operator()<"answer is '{:^^6.6A}'">(SV("answer is '^NAN^^'"), nan_pos); check.template operator()<"answer is '{:0>7.6A}'">(SV("answer is '000-NAN'"), nan_neg); check.template operator()<"answer is '{:0<7.6A}'">(SV("answer is '-NAN000'"), nan_neg); check.template operator()<"answer is '{:0^7.6A}'">(SV("answer is '0-NAN00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>014.6A}'">(SV("answer is ' 1.000000P-2'"), F(0.25)); check.template operator()<"answer is '{:<014.6A}'">(SV("answer is '1.000000P-2 '"), F(0.25)); check.template operator()<"answer is '{:^014.6A}'">(SV("answer is ' 1.000000P-2 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:.6A}'">(SV("answer is '0.000000P+0'"), F(0)); check.template operator()<"answer is '{:-.6A}'">(SV("answer is '0.000000P+0'"), F(0)); check.template operator()<"answer is '{:+.6A}'">(SV("answer is '+0.000000P+0'"), F(0)); check.template operator()<"answer is '{: .6A}'">(SV("answer is ' 0.000000P+0'"), F(0)); check.template operator()<"answer is '{:.6A}'">(SV("answer is '-0.000000P+0'"), F(-0.)); check.template operator()<"answer is '{:-.6A}'">(SV("answer is '-0.000000P+0'"), F(-0.)); check.template operator()<"answer is '{:+.6A}'">(SV("answer is '-0.000000P+0'"), F(-0.)); check.template operator()<"answer is '{: .6A}'">(SV("answer is '-0.000000P+0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:.6A}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-.6A}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+.6A}'">(SV("answer is '+INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: .6A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:.6A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-.6A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+.6A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: .6A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:.6A}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:-.6A}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:+.6A}'">(SV("answer is '+NAN'"), nan_pos); check.template operator()<"answer is '{: .6A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:.6A}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:-.6A}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:+.6A}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{: .6A}'">(SV("answer is '-NAN'"), nan_neg); // *** alternate form *** check.template operator()<"answer is '{:#.6A}'">(SV("answer is '1.400000P+1'"), F(2.5)); check.template operator()<"answer is '{:#.6A}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#.6A}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#.6A}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:#.6A}'">(SV("answer is '-NAN'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:011.6A}'">(SV("answer is '1.000000P-5'"), 0.03125); check.template operator()<"answer is '{:+012.6A}'">(SV("answer is '+1.000000P-5'"), 0.03125); check.template operator()<"answer is '{:+013.6A}'">(SV("answer is '+01.000000P-5'"), 0.03125); check.template operator()<"answer is '{:014.6A}'">(SV("answer is '0001.000000P-5'"), 0.03125); check.template operator()<"answer is '{:-014.6A}'">(SV("answer is '0001.000000P-5'"), 0.03125); check.template operator()<"answer is '{:+014.6A}'">(SV("answer is '+001.000000P-5'"), 0.03125); check.template operator()<"answer is '{: 014.6A}'">(SV("answer is ' 001.000000P-5'"), 0.03125); check.template operator()<"answer is '{:010.6A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010.6A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010.6A}'">(SV("answer is ' +INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010.6A}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010.6A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010.6A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010.6A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010.6A}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010.6A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:-010.6A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:+010.6A}'">(SV("answer is ' +NAN'"), nan_pos); check.template operator()<"answer is '{: 010.6A}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:010.6A}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:-010.6A}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:+010.6A}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{: 010.6A}'">(SV("answer is ' -NAN'"), nan_neg); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_scientific_lower_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:15e}'">(SV("answer is ' 2.500000e-01'"), F(0.25)); check.template operator()<"answer is '{:>15e}'">(SV("answer is ' 2.500000e-01'"), F(0.25)); check.template operator()<"answer is '{:<15e}'">(SV("answer is '2.500000e-01 '"), F(0.25)); check.template operator()<"answer is '{:^15e}'">(SV("answer is ' 2.500000e-01 '"), F(0.25)); check.template operator()<"answer is '{:->15e}'">(SV("answer is '---1.250000e-01'"), F(125e-3)); check.template operator()<"answer is '{:-<15e}'">(SV("answer is '1.250000e-01---'"), F(125e-3)); check.template operator()<"answer is '{:-^15e}'">(SV("answer is '-1.250000e-01--'"), F(125e-3)); check.template operator()<"answer is '{:*>6e}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6e}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6e}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7e}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7e}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7e}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6e}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6e}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6e}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7e}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7e}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7e}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>015e}'">(SV("answer is ' 2.500000e-01'"), F(0.25)); check.template operator()<"answer is '{:<015e}'">(SV("answer is '2.500000e-01 '"), F(0.25)); check.template operator()<"answer is '{:^015e}'">(SV("answer is ' 2.500000e-01 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:e}'">(SV("answer is '0.000000e+00'"), F(0)); check.template operator()<"answer is '{:-e}'">(SV("answer is '0.000000e+00'"), F(0)); check.template operator()<"answer is '{:+e}'">(SV("answer is '+0.000000e+00'"), F(0)); check.template operator()<"answer is '{: e}'">(SV("answer is ' 0.000000e+00'"), F(0)); check.template operator()<"answer is '{:e}'">(SV("answer is '-0.000000e+00'"), F(-0.)); check.template operator()<"answer is '{:-e}'">(SV("answer is '-0.000000e+00'"), F(-0.)); check.template operator()<"answer is '{:+e}'">(SV("answer is '-0.000000e+00'"), F(-0.)); check.template operator()<"answer is '{: e}'">(SV("answer is '-0.000000e+00'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:e}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-e}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+e}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: e}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:e}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-e}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+e}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: e}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:e}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-e}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+e}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: e}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:e}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-e}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+e}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: e}'">(SV("answer is '-nan'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0e}'">(SV("answer is '0e+00'"), F(0)); check.template operator()<"answer is '{:#.0e}'">(SV("answer is '0.e+00'"), F(0)); check.template operator()<"answer is '{:#e}'">(SV("answer is '0.000000e+00'"), F(0)); check.template operator()<"answer is '{:#e}'">(SV("answer is '2.500000e+00'"), F(2.5)); check.template operator()<"answer is '{:#e}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#e}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#e}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#e}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:07e}'">(SV("answer is '3.125000e-02'"), 0.03125); check.template operator()<"answer is '{:+07e}'">(SV("answer is '+3.125000e-02'"), 0.03125); check.template operator()<"answer is '{:+08e}'">(SV("answer is '+3.125000e-02'"), 0.03125); check.template operator()<"answer is '{:+09e}'">(SV("answer is '+3.125000e-02'"), 0.03125); check.template operator()<"answer is '{:014e}'">(SV("answer is '003.125000e-02'"), 0.03125); check.template operator()<"answer is '{:-014e}'">(SV("answer is '003.125000e-02'"), 0.03125); check.template operator()<"answer is '{:+014e}'">(SV("answer is '+03.125000e-02'"), 0.03125); check.template operator()<"answer is '{: 014e}'">(SV("answer is ' 03.125000e-02'"), 0.03125); check.template operator()<"answer is '{:010e}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010e}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010e}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010e}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010e}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010e}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010e}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010e}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010e}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010e}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010e}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010e}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010e}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010e}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010e}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010e}'">(SV("answer is ' -nan'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0e}'">(SV("answer is '3e-02'"), 0.03125); check.template operator()<"answer is '{:.1e}'">(SV("answer is '3.1e-02'"), 0.03125); check.template operator()<"answer is '{:.3e}'">(SV("answer is '3.125e-02'"), 0.03125); check.template operator()<"answer is '{:.10e}'">(SV("answer is '3.1250000000e-02'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_scientific_upper_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:15E}'">(SV("answer is ' 2.500000E-01'"), F(0.25)); check.template operator()<"answer is '{:>15E}'">(SV("answer is ' 2.500000E-01'"), F(0.25)); check.template operator()<"answer is '{:<15E}'">(SV("answer is '2.500000E-01 '"), F(0.25)); check.template operator()<"answer is '{:^15E}'">(SV("answer is ' 2.500000E-01 '"), F(0.25)); check.template operator()<"answer is '{:->15E}'">(SV("answer is '---1.250000E-01'"), F(125e-3)); check.template operator()<"answer is '{:-<15E}'">(SV("answer is '1.250000E-01---'"), F(125e-3)); check.template operator()<"answer is '{:-^15E}'">(SV("answer is '-1.250000E-01--'"), F(125e-3)); check.template operator()<"answer is '{:*>6E}'">(SV("answer is '***INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6E}'">(SV("answer is 'INF***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6E}'">(SV("answer is '*INF**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7E}'">(SV("answer is '###-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7E}'">(SV("answer is '-INF###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7E}'">(SV("answer is '#-INF##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6E}'">(SV("answer is '^^^NAN'"), nan_pos); check.template operator()<"answer is '{:^<6E}'">(SV("answer is 'NAN^^^'"), nan_pos); check.template operator()<"answer is '{:^^6E}'">(SV("answer is '^NAN^^'"), nan_pos); check.template operator()<"answer is '{:0>7E}'">(SV("answer is '000-NAN'"), nan_neg); check.template operator()<"answer is '{:0<7E}'">(SV("answer is '-NAN000'"), nan_neg); check.template operator()<"answer is '{:0^7E}'">(SV("answer is '0-NAN00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>015E}'">(SV("answer is ' 2.500000E-01'"), F(0.25)); check.template operator()<"answer is '{:<015E}'">(SV("answer is '2.500000E-01 '"), F(0.25)); check.template operator()<"answer is '{:^015E}'">(SV("answer is ' 2.500000E-01 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:E}'">(SV("answer is '0.000000E+00'"), F(0)); check.template operator()<"answer is '{:-E}'">(SV("answer is '0.000000E+00'"), F(0)); check.template operator()<"answer is '{:+E}'">(SV("answer is '+0.000000E+00'"), F(0)); check.template operator()<"answer is '{: E}'">(SV("answer is ' 0.000000E+00'"), F(0)); check.template operator()<"answer is '{:E}'">(SV("answer is '-0.000000E+00'"), F(-0.)); check.template operator()<"answer is '{:-E}'">(SV("answer is '-0.000000E+00'"), F(-0.)); check.template operator()<"answer is '{:+E}'">(SV("answer is '-0.000000E+00'"), F(-0.)); check.template operator()<"answer is '{: E}'">(SV("answer is '-0.000000E+00'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:E}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-E}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+E}'">(SV("answer is '+INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: E}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:E}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-E}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+E}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: E}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:E}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:-E}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:+E}'">(SV("answer is '+NAN'"), nan_pos); check.template operator()<"answer is '{: E}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:E}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:-E}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:+E}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{: E}'">(SV("answer is '-NAN'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0E}'">(SV("answer is '0E+00'"), F(0)); check.template operator()<"answer is '{:#.0E}'">(SV("answer is '0.E+00'"), F(0)); check.template operator()<"answer is '{:#E}'">(SV("answer is '0.000000E+00'"), F(0)); check.template operator()<"answer is '{:#E}'">(SV("answer is '2.500000E+00'"), F(2.5)); check.template operator()<"answer is '{:#E}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#E}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#E}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:#E}'">(SV("answer is '-NAN'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:07E}'">(SV("answer is '3.125000E-02'"), 0.03125); check.template operator()<"answer is '{:+07E}'">(SV("answer is '+3.125000E-02'"), 0.03125); check.template operator()<"answer is '{:+08E}'">(SV("answer is '+3.125000E-02'"), 0.03125); check.template operator()<"answer is '{:+09E}'">(SV("answer is '+3.125000E-02'"), 0.03125); check.template operator()<"answer is '{:014E}'">(SV("answer is '003.125000E-02'"), 0.03125); check.template operator()<"answer is '{:-014E}'">(SV("answer is '003.125000E-02'"), 0.03125); check.template operator()<"answer is '{:+014E}'">(SV("answer is '+03.125000E-02'"), 0.03125); check.template operator()<"answer is '{: 014E}'">(SV("answer is ' 03.125000E-02'"), 0.03125); check.template operator()<"answer is '{:010E}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010E}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010E}'">(SV("answer is ' +INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010E}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010E}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010E}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010E}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010E}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010E}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:-010E}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:+010E}'">(SV("answer is ' +NAN'"), nan_pos); check.template operator()<"answer is '{: 010E}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:010E}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:-010E}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:+010E}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{: 010E}'">(SV("answer is ' -NAN'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0E}'">(SV("answer is '3E-02'"), 0.03125); check.template operator()<"answer is '{:.1E}'">(SV("answer is '3.1E-02'"), 0.03125); check.template operator()<"answer is '{:.3E}'">(SV("answer is '3.125E-02'"), 0.03125); check.template operator()<"answer is '{:.10E}'">(SV("answer is '3.1250000000E-02'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_fixed_lower_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:11f}'">(SV("answer is ' 0.250000'"), F(0.25)); check.template operator()<"answer is '{:>11f}'">(SV("answer is ' 0.250000'"), F(0.25)); check.template operator()<"answer is '{:<11f}'">(SV("answer is '0.250000 '"), F(0.25)); check.template operator()<"answer is '{:^11f}'">(SV("answer is ' 0.250000 '"), F(0.25)); check.template operator()<"answer is '{:->11f}'">(SV("answer is '---0.125000'"), F(125e-3)); check.template operator()<"answer is '{:-<11f}'">(SV("answer is '0.125000---'"), F(125e-3)); check.template operator()<"answer is '{:-^11f}'">(SV("answer is '-0.125000--'"), F(125e-3)); check.template operator()<"answer is '{:*>6f}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6f}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6f}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7f}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7f}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7f}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6f}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6f}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6f}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7f}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7f}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7f}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>011f}'">(SV("answer is ' 0.250000'"), F(0.25)); check.template operator()<"answer is '{:<011f}'">(SV("answer is '0.250000 '"), F(0.25)); check.template operator()<"answer is '{:^011f}'">(SV("answer is ' 0.250000 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:f}'">(SV("answer is '0.000000'"), F(0)); check.template operator()<"answer is '{:-f}'">(SV("answer is '0.000000'"), F(0)); check.template operator()<"answer is '{:+f}'">(SV("answer is '+0.000000'"), F(0)); check.template operator()<"answer is '{: f}'">(SV("answer is ' 0.000000'"), F(0)); check.template operator()<"answer is '{:f}'">(SV("answer is '-0.000000'"), F(-0.)); check.template operator()<"answer is '{:-f}'">(SV("answer is '-0.000000'"), F(-0.)); check.template operator()<"answer is '{:+f}'">(SV("answer is '-0.000000'"), F(-0.)); check.template operator()<"answer is '{: f}'">(SV("answer is '-0.000000'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:f}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-f}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+f}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: f}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:f}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-f}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+f}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: f}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:f}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-f}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+f}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: f}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:f}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-f}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+f}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: f}'">(SV("answer is '-nan'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0f}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:#.0f}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#f}'">(SV("answer is '0.000000'"), F(0)); check.template operator()<"answer is '{:#f}'">(SV("answer is '2.500000'"), F(2.5)); check.template operator()<"answer is '{:#f}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#f}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#f}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#f}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:07f}'">(SV("answer is '0.031250'"), 0.03125); check.template operator()<"answer is '{:+07f}'">(SV("answer is '+0.031250'"), 0.03125); check.template operator()<"answer is '{:+08f}'">(SV("answer is '+0.031250'"), 0.03125); check.template operator()<"answer is '{:+09f}'">(SV("answer is '+0.031250'"), 0.03125); check.template operator()<"answer is '{:010f}'">(SV("answer is '000.031250'"), 0.03125); check.template operator()<"answer is '{:-010f}'">(SV("answer is '000.031250'"), 0.03125); check.template operator()<"answer is '{:+010f}'">(SV("answer is '+00.031250'"), 0.03125); check.template operator()<"answer is '{: 010f}'">(SV("answer is ' 00.031250'"), 0.03125); check.template operator()<"answer is '{:010f}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010f}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010f}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010f}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010f}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010f}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010f}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010f}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010f}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010f}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010f}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010f}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010f}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010f}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010f}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010f}'">(SV("answer is ' -nan'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0f}'">(SV("answer is '0'"), 0.03125); check.template operator()<"answer is '{:.1f}'">(SV("answer is '0.0'"), 0.03125); check.template operator()<"answer is '{:.5f}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.10f}'">(SV("answer is '0.0312500000'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_fixed_upper_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:11F}'">(SV("answer is ' 0.250000'"), F(0.25)); check.template operator()<"answer is '{:>11F}'">(SV("answer is ' 0.250000'"), F(0.25)); check.template operator()<"answer is '{:<11F}'">(SV("answer is '0.250000 '"), F(0.25)); check.template operator()<"answer is '{:^11F}'">(SV("answer is ' 0.250000 '"), F(0.25)); check.template operator()<"answer is '{:->11F}'">(SV("answer is '---0.125000'"), F(125e-3)); check.template operator()<"answer is '{:-<11F}'">(SV("answer is '0.125000---'"), F(125e-3)); check.template operator()<"answer is '{:-^11F}'">(SV("answer is '-0.125000--'"), F(125e-3)); check.template operator()<"answer is '{:*>6F}'">(SV("answer is '***INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6F}'">(SV("answer is 'INF***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6F}'">(SV("answer is '*INF**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7F}'">(SV("answer is '###-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7F}'">(SV("answer is '-INF###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7F}'">(SV("answer is '#-INF##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6F}'">(SV("answer is '^^^NAN'"), nan_pos); check.template operator()<"answer is '{:^<6F}'">(SV("answer is 'NAN^^^'"), nan_pos); check.template operator()<"answer is '{:^^6F}'">(SV("answer is '^NAN^^'"), nan_pos); check.template operator()<"answer is '{:0>7F}'">(SV("answer is '000-NAN'"), nan_neg); check.template operator()<"answer is '{:0<7F}'">(SV("answer is '-NAN000'"), nan_neg); check.template operator()<"answer is '{:0^7F}'">(SV("answer is '0-NAN00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>011F}'">(SV("answer is ' 0.250000'"), F(0.25)); check.template operator()<"answer is '{:<011F}'">(SV("answer is '0.250000 '"), F(0.25)); check.template operator()<"answer is '{:^011F}'">(SV("answer is ' 0.250000 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:F}'">(SV("answer is '0.000000'"), F(0)); check.template operator()<"answer is '{:-F}'">(SV("answer is '0.000000'"), F(0)); check.template operator()<"answer is '{:+F}'">(SV("answer is '+0.000000'"), F(0)); check.template operator()<"answer is '{: F}'">(SV("answer is ' 0.000000'"), F(0)); check.template operator()<"answer is '{:F}'">(SV("answer is '-0.000000'"), F(-0.)); check.template operator()<"answer is '{:-F}'">(SV("answer is '-0.000000'"), F(-0.)); check.template operator()<"answer is '{:+F}'">(SV("answer is '-0.000000'"), F(-0.)); check.template operator()<"answer is '{: F}'">(SV("answer is '-0.000000'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:F}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-F}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+F}'">(SV("answer is '+INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: F}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:F}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-F}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+F}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: F}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:F}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:-F}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:+F}'">(SV("answer is '+NAN'"), nan_pos); check.template operator()<"answer is '{: F}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:F}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:-F}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:+F}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{: F}'">(SV("answer is '-NAN'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0F}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:#.0F}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#F}'">(SV("answer is '0.000000'"), F(0)); check.template operator()<"answer is '{:#F}'">(SV("answer is '2.500000'"), F(2.5)); check.template operator()<"answer is '{:#F}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#F}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#F}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:#F}'">(SV("answer is '-NAN'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:07F}'">(SV("answer is '0.031250'"), 0.03125); check.template operator()<"answer is '{:+07F}'">(SV("answer is '+0.031250'"), 0.03125); check.template operator()<"answer is '{:+08F}'">(SV("answer is '+0.031250'"), 0.03125); check.template operator()<"answer is '{:+09F}'">(SV("answer is '+0.031250'"), 0.03125); check.template operator()<"answer is '{:010F}'">(SV("answer is '000.031250'"), 0.03125); check.template operator()<"answer is '{:-010F}'">(SV("answer is '000.031250'"), 0.03125); check.template operator()<"answer is '{:+010F}'">(SV("answer is '+00.031250'"), 0.03125); check.template operator()<"answer is '{: 010F}'">(SV("answer is ' 00.031250'"), 0.03125); check.template operator()<"answer is '{:010F}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010F}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010F}'">(SV("answer is ' +INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010F}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010F}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010F}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010F}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010F}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010F}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:-010F}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:+010F}'">(SV("answer is ' +NAN'"), nan_pos); check.template operator()<"answer is '{: 010F}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:010F}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:-010F}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:+010F}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{: 010F}'">(SV("answer is ' -NAN'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0F}'">(SV("answer is '0'"), 0.03125); check.template operator()<"answer is '{:.1F}'">(SV("answer is '0.0'"), 0.03125); check.template operator()<"answer is '{:.5F}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.10F}'">(SV("answer is '0.0312500000'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_general_lower_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:7g}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:>7g}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<7g}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^7g}'">(SV("answer is ' 0.25 '"), F(0.25)); check.template operator()<"answer is '{:->8g}'">(SV("answer is '---0.125'"), F(125e-3)); check.template operator()<"answer is '{:-<8g}'">(SV("answer is '0.125---'"), F(125e-3)); check.template operator()<"answer is '{:-^8g}'">(SV("answer is '-0.125--'"), F(125e-3)); check.template operator()<"answer is '{:*>6g}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6g}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6g}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7g}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7g}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7g}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6g}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6g}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6g}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7g}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7g}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7g}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07g}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<07g}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^07g}'">(SV("answer is ' 0.25 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:g}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:-g}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:+g}'">(SV("answer is '+0'"), F(0)); check.template operator()<"answer is '{: g}'">(SV("answer is ' 0'"), F(0)); check.template operator()<"answer is '{:g}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:-g}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:+g}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{: g}'">(SV("answer is '-0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:g}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-g}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+g}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: g}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:g}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-g}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+g}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: g}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:g}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-g}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+g}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: g}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:g}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-g}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+g}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: g}'">(SV("answer is '-nan'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0g}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:#.0g}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#g}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#g}'">(SV("answer is '2.5'"), F(2.5)); check.template operator()<"answer is '{:#g}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#g}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#g}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#g}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:06g}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:+06g}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+07g}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+08g}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:09g}'">(SV("answer is '000.03125'"), 0.03125); check.template operator()<"answer is '{:-09g}'">(SV("answer is '000.03125'"), 0.03125); check.template operator()<"answer is '{:+09g}'">(SV("answer is '+00.03125'"), 0.03125); check.template operator()<"answer is '{: 09g}'">(SV("answer is ' 00.03125'"), 0.03125); check.template operator()<"answer is '{:010g}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010g}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010g}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010g}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010g}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010g}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010g}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010g}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010g}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010g}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010g}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010g}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010g}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010g}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010g}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010g}'">(SV("answer is ' -nan'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0g}'">(SV("answer is '0.03'"), 0.03125); check.template operator()<"answer is '{:.1g}'">(SV("answer is '0.03'"), 0.03125); check.template operator()<"answer is '{:.2g}'">(SV("answer is '0.031'"), 0.03125); check.template operator()<"answer is '{:.3g}'">(SV("answer is '0.0312'"), 0.03125); check.template operator()<"answer is '{:.4g}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.5g}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.10g}'">(SV("answer is '0.03125'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_general_upper_case(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:7G}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:>7G}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<7G}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^7G}'">(SV("answer is ' 0.25 '"), F(0.25)); check.template operator()<"answer is '{:->8G}'">(SV("answer is '---0.125'"), F(125e-3)); check.template operator()<"answer is '{:-<8G}'">(SV("answer is '0.125---'"), F(125e-3)); check.template operator()<"answer is '{:-^8G}'">(SV("answer is '-0.125--'"), F(125e-3)); check.template operator()<"answer is '{:*>6G}'">(SV("answer is '***INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6G}'">(SV("answer is 'INF***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6G}'">(SV("answer is '*INF**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7G}'">(SV("answer is '###-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7G}'">(SV("answer is '-INF###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7G}'">(SV("answer is '#-INF##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6G}'">(SV("answer is '^^^NAN'"), nan_pos); check.template operator()<"answer is '{:^<6G}'">(SV("answer is 'NAN^^^'"), nan_pos); check.template operator()<"answer is '{:^^6G}'">(SV("answer is '^NAN^^'"), nan_pos); check.template operator()<"answer is '{:0>7G}'">(SV("answer is '000-NAN'"), nan_neg); check.template operator()<"answer is '{:0<7G}'">(SV("answer is '-NAN000'"), nan_neg); check.template operator()<"answer is '{:0^7G}'">(SV("answer is '0-NAN00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07G}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<07G}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^07G}'">(SV("answer is ' 0.25 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:G}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:-G}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:+G}'">(SV("answer is '+0'"), F(0)); check.template operator()<"answer is '{: G}'">(SV("answer is ' 0'"), F(0)); check.template operator()<"answer is '{:G}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:-G}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:+G}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{: G}'">(SV("answer is '-0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:G}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-G}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+G}'">(SV("answer is '+INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: G}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:G}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-G}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+G}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: G}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:G}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:-G}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:+G}'">(SV("answer is '+NAN'"), nan_pos); check.template operator()<"answer is '{: G}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:G}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:-G}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{:+G}'">(SV("answer is '-NAN'"), nan_neg); check.template operator()<"answer is '{: G}'">(SV("answer is '-NAN'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0G}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:#.0G}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#G}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#G}'">(SV("answer is '2.5'"), F(2.5)); check.template operator()<"answer is '{:#G}'">(SV("answer is 'INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#G}'">(SV("answer is '-INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#G}'">(SV("answer is 'NAN'"), nan_pos); check.template operator()<"answer is '{:#G}'">(SV("answer is '-NAN'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:06G}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:+06G}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+07G}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+08G}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:09G}'">(SV("answer is '000.03125'"), 0.03125); check.template operator()<"answer is '{:-09G}'">(SV("answer is '000.03125'"), 0.03125); check.template operator()<"answer is '{:+09G}'">(SV("answer is '+00.03125'"), 0.03125); check.template operator()<"answer is '{: 09G}'">(SV("answer is ' 00.03125'"), 0.03125); check.template operator()<"answer is '{:010G}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010G}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010G}'">(SV("answer is ' +INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010G}'">(SV("answer is ' INF'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010G}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010G}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010G}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010G}'">(SV("answer is ' -INF'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010G}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:-010G}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:+010G}'">(SV("answer is ' +NAN'"), nan_pos); check.template operator()<"answer is '{: 010G}'">(SV("answer is ' NAN'"), nan_pos); check.template operator()<"answer is '{:010G}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:-010G}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{:+010G}'">(SV("answer is ' -NAN'"), nan_neg); check.template operator()<"answer is '{: 010G}'">(SV("answer is ' -NAN'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0G}'">(SV("answer is '0.03'"), 0.03125); check.template operator()<"answer is '{:.1G}'">(SV("answer is '0.03'"), 0.03125); check.template operator()<"answer is '{:.2G}'">(SV("answer is '0.031'"), 0.03125); check.template operator()<"answer is '{:.3G}'">(SV("answer is '0.0312'"), 0.03125); check.template operator()<"answer is '{:.4G}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.5G}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.10G}'">(SV("answer is '0.03125'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_default(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:7}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:>7}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<7}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^7}'">(SV("answer is ' 0.25 '"), F(0.25)); check.template operator()<"answer is '{:->8}'">(SV("answer is '---0.125'"), F(125e-3)); check.template operator()<"answer is '{:-<8}'">(SV("answer is '0.125---'"), F(125e-3)); check.template operator()<"answer is '{:-^8}'">(SV("answer is '-0.125--'"), F(125e-3)); check.template operator()<"answer is '{:*>6}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<07}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^07}'">(SV("answer is ' 0.25 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:-}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:+}'">(SV("answer is '+0'"), F(0)); check.template operator()<"answer is '{: }'">(SV("answer is ' 0'"), F(0)); check.template operator()<"answer is '{:}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:-}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:+}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{: }'">(SV("answer is '-0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: }'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: }'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: }'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: }'">(SV("answer is '-nan'"), nan_neg); // *** alternate form *** check.template operator()<"answer is '{:#}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#}'">(SV("answer is '2.5'"), F(2.5)); check.template operator()<"answer is '{:#}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:07}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:+07}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+08}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+09}'">(SV("answer is '+00.03125'"), 0.03125); check.template operator()<"answer is '{:010}'">(SV("answer is '0000.03125'"), 0.03125); check.template operator()<"answer is '{:-010}'">(SV("answer is '0000.03125'"), 0.03125); check.template operator()<"answer is '{:+010}'">(SV("answer is '+000.03125'"), 0.03125); check.template operator()<"answer is '{: 010}'">(SV("answer is ' 000.03125'"), 0.03125); check.template operator()<"answer is '{:010}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010}'">(SV("answer is ' -nan'"), nan_neg); // *** precision *** // See format_test_floating_point_default_precision // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point_default_precision(TestFunction check) { auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" // *** align-fill & width *** check.template operator()<"answer is '{:7.6}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:>7.6}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<7.6}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^7.6}'">(SV("answer is ' 0.25 '"), F(0.25)); check.template operator()<"answer is '{:->8.6}'">(SV("answer is '---0.125'"), F(125e-3)); check.template operator()<"answer is '{:-<8.6}'">(SV("answer is '0.125---'"), F(125e-3)); check.template operator()<"answer is '{:-^8.6}'">(SV("answer is '-0.125--'"), F(125e-3)); check.template operator()<"answer is '{:*>6.6}'">(SV("answer is '***inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*<6.6}'">(SV("answer is 'inf***'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:*^6.6}'">(SV("answer is '*inf**'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#>7.6}'">(SV("answer is '###-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#<7.6}'">(SV("answer is '-inf###'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#^7.6}'">(SV("answer is '#-inf##'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:^>6.6}'">(SV("answer is '^^^nan'"), nan_pos); check.template operator()<"answer is '{:^<6.6}'">(SV("answer is 'nan^^^'"), nan_pos); check.template operator()<"answer is '{:^^6.6}'">(SV("answer is '^nan^^'"), nan_pos); check.template operator()<"answer is '{:0>7.6}'">(SV("answer is '000-nan'"), nan_neg); check.template operator()<"answer is '{:0<7.6}'">(SV("answer is '-nan000'"), nan_neg); check.template operator()<"answer is '{:0^7.6}'">(SV("answer is '0-nan00'"), nan_neg); // Test whether zero padding is ignored check.template operator()<"answer is '{:>07.6}'">(SV("answer is ' 0.25'"), F(0.25)); check.template operator()<"answer is '{:<07.6}'">(SV("answer is '0.25 '"), F(0.25)); check.template operator()<"answer is '{:^07.6}'">(SV("answer is ' 0.25 '"), F(0.25)); // *** Sign *** check.template operator()<"answer is '{:.6}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:-.6}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:+.6}'">(SV("answer is '+0'"), F(0)); check.template operator()<"answer is '{: .6}'">(SV("answer is ' 0'"), F(0)); check.template operator()<"answer is '{:.6}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:-.6}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{:+.6}'">(SV("answer is '-0'"), F(-0.)); check.template operator()<"answer is '{: .6}'">(SV("answer is '-0'"), F(-0.)); // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. check.template operator()<"answer is '{:.6}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-.6}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+.6}'">(SV("answer is '+inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: .6}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:.6}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-.6}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+.6}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: .6}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:.6}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:-.6}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:+.6}'">(SV("answer is '+nan'"), nan_pos); check.template operator()<"answer is '{: .6}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:.6}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:-.6}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{:+.6}'">(SV("answer is '-nan'"), nan_neg); check.template operator()<"answer is '{: .6}'">(SV("answer is '-nan'"), nan_neg); // *** alternate form ** // When precision is zero there's no decimal point except when the alternate form is specified. check.template operator()<"answer is '{:.0}'">(SV("answer is '0'"), F(0)); check.template operator()<"answer is '{:#.0}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#.6}'">(SV("answer is '0.'"), F(0)); check.template operator()<"answer is '{:#.6}'">(SV("answer is '2.5'"), F(2.5)); check.template operator()<"answer is '{:#.6}'">(SV("answer is 'inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:#.6}'">(SV("answer is '-inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:#.6}'">(SV("answer is 'nan'"), nan_pos); check.template operator()<"answer is '{:#.6}'">(SV("answer is '-nan'"), nan_neg); // *** zero-padding & width *** check.template operator()<"answer is '{:06.6}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:+06.6}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+07.6}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:+08.6}'">(SV("answer is '+0.03125'"), 0.03125); check.template operator()<"answer is '{:09.6}'">(SV("answer is '000.03125'"), 0.03125); check.template operator()<"answer is '{:-09.6}'">(SV("answer is '000.03125'"), 0.03125); check.template operator()<"answer is '{:+09.6}'">(SV("answer is '+00.03125'"), 0.03125); check.template operator()<"answer is '{: 09.6}'">(SV("answer is ' 00.03125'"), 0.03125); check.template operator()<"answer is '{:010.6}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010.6}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010.6}'">(SV("answer is ' +inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010.6}'">(SV("answer is ' inf'"), std::numeric_limits::infinity()); check.template operator()<"answer is '{:010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:-010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:+010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{: 010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits::infinity()); check.template operator()<"answer is '{:010.6}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:-010.6}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:+010.6}'">(SV("answer is ' +nan'"), nan_pos); check.template operator()<"answer is '{: 010.6}'">(SV("answer is ' nan'"), nan_pos); check.template operator()<"answer is '{:010.6}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:-010.6}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{:+010.6}'">(SV("answer is ' -nan'"), nan_neg); check.template operator()<"answer is '{: 010.6}'">(SV("answer is ' -nan'"), nan_neg); // *** precision *** check.template operator()<"answer is '{:.0}'">(SV("answer is '0.03'"), 0.03125); check.template operator()<"answer is '{:.1}'">(SV("answer is '0.03'"), 0.03125); check.template operator()<"answer is '{:.2}'">(SV("answer is '0.031'"), 0.03125); check.template operator()<"answer is '{:.3}'">(SV("answer is '0.0312'"), 0.03125); check.template operator()<"answer is '{:.4}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.5}'">(SV("answer is '0.03125'"), 0.03125); check.template operator()<"answer is '{:.10}'">(SV("answer is '0.03125'"), 0.03125); // *** locale-specific form *** // See locale-specific_form.pass.cpp } template void format_test_floating_point(TestFunction check, ExceptionTest check_exception) { format_test_floating_point_hex_lower_case(check); format_test_floating_point_hex_upper_case(check); format_test_floating_point_hex_lower_case_precision(check); format_test_floating_point_hex_upper_case_precision(check); format_test_floating_point_scientific_lower_case(check); format_test_floating_point_scientific_upper_case(check); format_test_floating_point_fixed_lower_case(check); format_test_floating_point_fixed_upper_case(check); format_test_floating_point_general_lower_case(check); format_test_floating_point_general_upper_case(check); format_test_floating_point_default(check); format_test_floating_point_default_precision(check); // *** type *** for (const auto& fmt : invalid_types("aAeEfFgG")) check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, F(1)); } template void format_test_floating_point(TestFunction check, ExceptionTest check_exception) { format_test_floating_point(check, check_exception); format_test_floating_point(check, check_exception); format_test_floating_point(check, check_exception); } template void format_test_pointer(TestFunction check, ExceptionTest check_exception) { // *** align-fill & width *** check.template operator()<"answer is '{:6}'">(SV("answer is ' 0x0'"), P(nullptr)); check.template operator()<"answer is '{:>6}'">(SV("answer is ' 0x0'"), P(nullptr)); check.template operator()<"answer is '{:<6}'">(SV("answer is '0x0 '"), P(nullptr)); check.template operator()<"answer is '{:^6}'">(SV("answer is ' 0x0 '"), P(nullptr)); check.template operator()<"answer is '{:->6}'">(SV("answer is '---0x0'"), P(nullptr)); check.template operator()<"answer is '{:-<6}'">(SV("answer is '0x0---'"), P(nullptr)); check.template operator()<"answer is '{:-^6}'">(SV("answer is '-0x0--'"), P(nullptr)); // *** Sign *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), P(nullptr)); check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), P(nullptr)); check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), P(nullptr)); // *** alternate form *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), P(nullptr)); // *** zero-padding *** check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), P(nullptr)); // *** precision *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), P(nullptr)); // *** locale-specific form *** check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), P(nullptr)); // *** type *** for (const auto& fmt : invalid_types("p")) check_exception("The format-spec type has a type not supported for a pointer argument", fmt, P(nullptr)); } template void format_test_handle(TestFunction check, ExceptionTest check_exception) { // *** Valid permuatations *** check.template operator()<"answer is '{}'">(SV("answer is '0xaaaa'"), status::foo); check.template operator()<"answer is '{:x}'">(SV("answer is '0xaaaa'"), status::foo); check.template operator()<"answer is '{:X}'">(SV("answer is '0XAAAA'"), status::foo); check.template operator()<"answer is '{:s}'">(SV("answer is 'foo'"), status::foo); check.template operator()<"answer is '{}'">(SV("answer is '0x5555'"), status::bar); check.template operator()<"answer is '{:x}'">(SV("answer is '0x5555'"), status::bar); check.template operator()<"answer is '{:X}'">(SV("answer is '0X5555'"), status::bar); check.template operator()<"answer is '{:s}'">(SV("answer is 'bar'"), status::bar); check.template operator()<"answer is '{}'">(SV("answer is '0xaa55'"), status::foobar); check.template operator()<"answer is '{:x}'">(SV("answer is '0xaa55'"), status::foobar); check.template operator()<"answer is '{:X}'">(SV("answer is '0XAA55'"), status::foobar); check.template operator()<"answer is '{:s}'">(SV("answer is 'foobar'"), status::foobar); // *** type *** for (const auto& fmt : invalid_types("xXs")) check_exception("The format-spec type has a type not supported for a status argument", fmt, status::foo); } template void format_test_pointer(TestFunction check, ExceptionTest check_exception) { format_test_pointer(check, check_exception); format_test_pointer(check, check_exception); format_test_pointer(check, check_exception); } template void format_tests(TestFunction check, ExceptionTest check_exception) { // *** Test escaping *** check.template operator()<"{{">(SV("{")); check.template operator()<"}}">(SV("}")); // *** Test argument ID *** check.template operator()<"hello {0:} {1:}">(SV("hello false true"), false, true); check.template operator()<"hello {1:} {0:}">(SV("hello true false"), false, true); // *** Test many arguments *** // [format.args]/1 // An instance of basic_format_args provides access to formatting arguments. // Implementations should optimize the representation of basic_format_args // for a small number of formatting arguments. // // These's no guidances what "a small number of formatting arguments" is. // - fmtlib uses a 15 elements // - libc++ uses 12 elements // - MSVC STL uses a different approach regardless of the number of arguments // - libstdc++ has no implementation yet // fmtlib and libc++ use a similar approach, this approach can support 16 // elements (based on design choices both support less elements). This test // makes sure "the large number of formatting arguments" code path is tested. check.template operator()<"{}{}{}{}{}{}{}{}{}{}\t{}{}{}{}{}{}{}{}{}{}">(SV("1234567890\t1234567890"), 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0); // ** Test invalid format strings *** check_exception("The format string terminates at a '{'", SV("{")); check_exception("The replacement field misses a terminating '}'", SV("{:"), 42); check_exception("The format string contains an invalid escape sequence", SV("}")); check_exception("The format string contains an invalid escape sequence", SV("{:}-}"), 42); check_exception("The format string contains an invalid escape sequence", SV("} ")); check_exception("The arg-id of the format-spec starts with an invalid character", SV("{-"), 42); check_exception("Argument index out of bounds", SV("hello {}")); check_exception("Argument index out of bounds", SV("hello {0}")); check_exception("Argument index out of bounds", SV("hello {1}"), 42); // *** Test char format argument *** // The `char` to `wchar_t` formatting is tested separately. check.template operator()<"hello {}{}{}{}{}{}{}">(SV("hello 09azAZ!"), CharT('0'), CharT('9'), CharT('a'), CharT('z'), CharT('A'), CharT('Z'), CharT('!')); format_test_char(check, check_exception); format_test_char_as_integer(check, check_exception); // *** Test string format argument *** { CharT buffer[] = {CharT('0'), CharT('9'), CharT('a'), CharT('z'), CharT('A'), CharT('Z'), CharT('!'), 0}; CharT* data = buffer; check.template operator()<"hello {}">(SV("hello 09azAZ!"), data); } { CharT buffer[] = {CharT('0'), CharT('9'), CharT('a'), CharT('z'), CharT('A'), CharT('Z'), CharT('!'), 0}; const CharT* data = buffer; check.template operator()<"hello {}">(SV("hello 09azAZ!"), data); } { std::basic_string data = STR("world"); check.template operator()<"hello {}">(SV("hello world"), data); } { std::basic_string buffer = STR("world"); std::basic_string_view data = buffer; check.template operator()<"hello {}">(SV("hello world"), data); } format_string_tests(check, check_exception); // *** Test Boolean format argument *** check.template operator()<"hello {} {}">(SV("hello false true"), false, true); format_test_bool(check, check_exception); format_test_bool_as_integer(check, check_exception); // *** Test signed integral format argument *** check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); #ifndef TEST_HAS_NO_INT128 check.template operator()<"hello {}">(SV("hello 42"), static_cast<__int128_t>(42)); { // Note 128-bit support is only partly implemented test the range // conditions here. static constexpr auto fmt = string_literal("{}"); std::basic_string min = std::format(fmt.template sv(), std::numeric_limits::min()); check.template operator()<"{}">(std::basic_string_view(min), static_cast<__int128_t>(std::numeric_limits::min())); std::basic_string max = std::format(fmt.template sv(), std::numeric_limits::max()); check.template operator()<"{}">(std::basic_string_view(max), static_cast<__int128_t>(std::numeric_limits::max())); check_exception("128-bit value is outside of implemented range", SV("{}"), static_cast<__int128_t>(std::numeric_limits::min()) - 1); check_exception("128-bit value is outside of implemented range", SV("{}"), static_cast<__int128_t>(std::numeric_limits::max()) + 1); } #endif format_test_signed_integer(check, check_exception); // ** Test unsigned integral format argument *** check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); #ifndef TEST_HAS_NO_INT128 check.template operator()<"hello {}">(SV("hello 42"), static_cast<__uint128_t>(42)); { // Note 128-bit support is only partly implemented test the range // conditions here. static constexpr auto fmt = string_literal("{}"); std::basic_string max = std::format(fmt.template sv(), std::numeric_limits::max()); check.template operator()<"{}">(std::basic_string_view(max), static_cast<__uint128_t>(std::numeric_limits::max())); check_exception("128-bit value is outside of implemented range", SV("{}"), static_cast<__uint128_t>(std::numeric_limits::max()) + 1); } #endif format_test_unsigned_integer(check, check_exception); // *** Test floating point format argument *** check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); check.template operator()<"hello {}">(SV("hello 42"), static_cast(42)); format_test_floating_point(check, check_exception); // *** Test pointer formater argument *** check.template operator()<"hello {}">(SV("hello 0x0"), nullptr); check.template operator()<"hello {}">(SV("hello 0x42"), reinterpret_cast(0x42)); check.template operator()<"hello {}">(SV("hello 0x42"), reinterpret_cast(0x42)); format_test_pointer(check, check_exception); // *** Test handle formatter argument *** format_test_handle(check, check_exception); } #ifndef TEST_HAS_NO_WIDE_CHARACTERS template void format_tests_char_to_wchar_t(TestFunction check) { using CharT = wchar_t; check.template operator()<"hello {}{}{}{}{}">(SV("hello 09azA"), '0', '9', 'a', 'z', 'A'); } #endif #endif