blob: ba6f67b0e24fd19095158c3e910782c77805f5d9 [file] [log] [blame]
//===----------------------------------------------------------------------===//
// 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 <format>
#include <algorithm>
#include <cassert>
#include <charconv>
#include <cmath>
#include <cstdint>
#include <iterator>
#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 <class T>
struct context {};
template <>
struct context<char> {
using type = std::format_context;
};
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
template <>
struct context<wchar_t> {
using type = std::wformat_context;
};
#endif
template <class T>
using context_t = typename context<T>::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 <class CharT>
struct std::formatter<status, CharT> {
int type = 0;
constexpr auto parse(basic_format_parse_context<CharT>& 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 <class Out>
auto format(status s, basic_format_context<Out, CharT>& ctx) -> decltype(ctx.out()) {
const char* names[] = {"foo", "bar", "foobar"};
char buffer[7];
const char* begin = names[0];
const char* end = names[0];
switch (type) {
case 0:
begin = buffer;
buffer[0] = '0';
buffer[1] = 'x';
end = std::to_chars(&buffer[2], std::end(buffer), static_cast<uint16_t>(s), 16).ptr;
buffer[6] = '\0';
break;
case 1:
begin = buffer;
buffer[0] = '0';
buffer[1] = 'X';
end = std::to_chars(&buffer[2], std::end(buffer), static_cast<uint16_t>(s), 16).ptr;
std::transform(static_cast<const char*>(&buffer[2]), end, &buffer[2], [](char c) {
return static_cast<char>(std::toupper(c)); });
buffer[6] = '\0';
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 <class CharT>
std::vector<std::basic_string_view<CharT>> invalid_types(std::string valid) {
std::vector<std::basic_string_view<CharT>> 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 <class CharT, class W, class U, class TestFunction, class ExceptionTest>
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 <<<world"), world);
check.template operator()<"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<CharT>("s"))
check_exception("The format-spec type has a type not supported for a string argument", fmt, world);
}
template <class CharT, class TestFunction>
void format_test_string_unicode([[maybe_unused]] TestFunction check) {
// unicode.pass.cpp and ascii.pass.cpp have additional tests.
#ifndef TEST_HAS_NO_UNICODE
// Make sure all possible types are tested. For clarity don't use macros.
if constexpr (std::same_as<CharT, char>) {
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<char*>(c_string));
check.template operator()<"{:*^4.2}">(SV("*aß*"), const_cast<char*>(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<wchar_t*>(c_string));
check.template operator()<"{:*^4.2}">(SV("*aß*"), const_cast<wchar_t*>(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 // TEST_HAS_NO_WIDE_CHARACTERS
// ß 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"));
// Examples used in P1868R2
check.template operator()<"{:*^3}">(SV("*\u0041*"), STR("\u0041")); // { LATIN CAPITAL LETTER A }
check.template operator()<"{:*^3}">(SV("*\u00c1*"), STR("\u00c1")); // { LATIN CAPITAL LETTER A WITH ACUTE }
check.template operator()<"{:*^3}">(
SV("*\u0041\u0301*"),
STR("\u0041\u0301")); // { LATIN CAPITAL LETTER A } { COMBINING ACUTE ACCENT }
check.template operator()<"{:*^3}">(SV("*\u0132*"), STR("\u0132")); // { LATIN CAPITAL LIGATURE IJ }
check.template operator()<"{:*^3}">(SV("*\u0394*"), STR("\u0394")); // { GREEK CAPITAL LETTER DELTA }
check.template operator()<"{:*^3}">(SV("*\u0429*"), STR("\u0429")); // { CYRILLIC CAPITAL LETTER SHCHA }
check.template operator()<"{:*^3}">(SV("*\u05d0*"), STR("\u05d0")); // { HEBREW LETTER ALEF }
check.template operator()<"{:*^3}">(SV("*\u0634*"), STR("\u0634")); // { ARABIC LETTER SHEEN }
check.template operator()<"{:*^4}">(SV("*\u3009*"), STR("\u3009")); // { RIGHT-POINTING ANGLE BRACKET }
check.template operator()<"{:*^4}">(SV("*\u754c*"), STR("\u754c")); // { CJK Unified Ideograph-754C }
check.template operator()<"{:*^4}">(SV("*\U0001f921*"), STR("\U0001f921")); // { UNICORN FACE }
check.template operator()<"{:*^4}">(
SV("*\U0001f468\u200d\U0001F469\u200d\U0001F467\u200d\U0001F466*"),
STR("\U0001f468\u200d\U0001F469\u200d\U0001F467\u200d\U0001F466")); // { Family: Man, Woman, Girl, Boy }
#endif // TEST_HAS_NO_UNICODE
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_string_tests(TestFunction check, ExceptionTest check_exception) {
std::basic_string<CharT> world = STR("world");
std::basic_string<CharT> universe = STR("universe");
// Test a string literal in a way it won't decay to a pointer.
if constexpr (std::same_as<CharT, char>)
format_test_string<CharT>("world", "universe", check, check_exception);
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
else
format_test_string<CharT>(L"world", L"universe", check, check_exception);
#endif
format_test_string<CharT>(world.c_str(), universe.c_str(), check, check_exception);
format_test_string<CharT>(const_cast<CharT*>(world.c_str()), const_cast<CharT*>(universe.c_str()), check,
check_exception);
format_test_string<CharT>(std::basic_string_view<CharT>(world), std::basic_string_view<CharT>(universe), check,
check_exception);
format_test_string<CharT>(world, universe, check, check_exception);
format_test_string_unicode<CharT>(check);
}
template <class CharT, class TestFunction, class ExceptionTest>
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<CharT>("bBdosxX"))
check_exception("The format-spec type has a type not supported for a bool argument", fmt, true);
}
template <class CharT, class TestFunction, class ExceptionTest>
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<CharT>("bBcdosxX"))
check_exception("The format-spec type has a type not supported for a bool argument", fmt, true);
}
template <class I, class CharT, class TestFunction, class ExceptionTest>
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<I>)
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<I>)
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<I>)
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<I>)
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<I>) {
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<I>) {
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<CharT>("bBcdoxX"))
check_exception("The format-spec type has a type not supported for an integer argument", fmt, 42);
}
template <class I, class CharT, class TestFunction, class ExceptionTest>
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<CharT>("bBcdoxX"))
check_exception("The format-spec type has a type not supported for an integer argument", fmt, I(42));
// *** Validate range ***
// The code has some duplications to keep the if statement readable.
if constexpr (std::signed_integral<CharT>) {
if constexpr (std::signed_integral<I> && sizeof(I) > sizeof(CharT)) {
check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits<I>::min());
check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits<I>::max());
} else if constexpr (std::unsigned_integral<I> && sizeof(I) >= sizeof(CharT)) {
check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits<I>::max());
}
} else if constexpr (sizeof(I) > sizeof(CharT)) {
check_exception("Integral value outside the range of the char type", SV("{:c}"), std::numeric_limits<I>::max());
}
}
template <class I, class CharT, class TestFunction, class ExceptionTest>
void format_test_integer(TestFunction check, ExceptionTest check_exception) {
format_test_integer_as_integer<I, CharT>(check, check_exception);
format_test_integer_as_char<I, CharT>(check, check_exception);
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_signed_integer(TestFunction check, ExceptionTest check_exception) {
format_test_integer<signed char, CharT>(check, check_exception);
format_test_integer<short, CharT>(check, check_exception);
format_test_integer<int, CharT>(check, check_exception);
format_test_integer<long, CharT>(check, check_exception);
format_test_integer<long long, CharT>(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<int8_t>::min());
check.template operator()<"{:#o}">(SV("-0200"), std::numeric_limits<int8_t>::min());
check.template operator()<"{:#}">(SV("-128"), std::numeric_limits<int8_t>::min());
check.template operator()<"{:#x}">(SV("-0x80"), std::numeric_limits<int8_t>::min());
check.template operator()<"{:#b}">(SV("-0b1000000000000000"), std::numeric_limits<int16_t>::min());
check.template operator()<"{:#o}">(SV("-0100000"), std::numeric_limits<int16_t>::min());
check.template operator()<"{:#}">(SV("-32768"), std::numeric_limits<int16_t>::min());
check.template operator()<"{:#x}">(SV("-0x8000"), std::numeric_limits<int16_t>::min());
check.template operator()<"{:#b}">(SV("-0b10000000000000000000000000000000"), std::numeric_limits<int32_t>::min());
check.template operator()<"{:#o}">(SV("-020000000000"), std::numeric_limits<int32_t>::min());
check.template operator()<"{:#}">(SV("-2147483648"), std::numeric_limits<int32_t>::min());
check.template operator()<"{:#x}">(SV("-0x80000000"), std::numeric_limits<int32_t>::min());
check.template operator()<"{:#b}">(SV("-0b1000000000000000000000000000000000000000000000000000000000000000"),
std::numeric_limits<int64_t>::min());
check.template operator()<"{:#o}">(SV("-01000000000000000000000"), std::numeric_limits<int64_t>::min());
check.template operator()<"{:#}">(SV("-9223372036854775808"), std::numeric_limits<int64_t>::min());
check.template operator()<"{:#x}">(SV("-0x8000000000000000"), std::numeric_limits<int64_t>::min());
#ifndef TEST_HAS_NO_INT128
check.template operator()<"{:#b}">(
SV("-0b1000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"),
std::numeric_limits<__int128_t>::min());
check.template
operator()<"{:#o}">(SV("-02000000000000000000000000000000000000000000"), std::numeric_limits<__int128_t>::min());
check.template
operator()<"{:#}">(SV("-170141183460469231731687303715884105728"), std::numeric_limits<__int128_t>::min());
check.template operator()<"{:#x}">(SV("-0x80000000000000000000000000000000"), std::numeric_limits<__int128_t>::min());
#endif
check.template operator()<"{:#b}">(SV("0b1111111"), std::numeric_limits<int8_t>::max());
check.template operator()<"{:#o}">(SV("0177"), std::numeric_limits<int8_t>::max());
check.template operator()<"{:#}">(SV("127"), std::numeric_limits<int8_t>::max());
check.template operator()<"{:#x}">(SV("0x7f"), std::numeric_limits<int8_t>::max());
check.template operator()<"{:#b}">(SV("0b111111111111111"), std::numeric_limits<int16_t>::max());
check.template operator()<"{:#o}">(SV("077777"), std::numeric_limits<int16_t>::max());
check.template operator()<"{:#}">(SV("32767"), std::numeric_limits<int16_t>::max());
check.template operator()<"{:#x}">(SV("0x7fff"), std::numeric_limits<int16_t>::max());
check.template operator()<"{:#b}">(SV("0b1111111111111111111111111111111"), std::numeric_limits<int32_t>::max());
check.template operator()<"{:#o}">(SV("017777777777"), std::numeric_limits<int32_t>::max());
check.template operator()<"{:#}">(SV("2147483647"), std::numeric_limits<int32_t>::max());
check.template operator()<"{:#x}">(SV("0x7fffffff"), std::numeric_limits<int32_t>::max());
check.template operator()<"{:#b}">(SV("0b111111111111111111111111111111111111111111111111111111111111111"),
std::numeric_limits<int64_t>::max());
check.template operator()<"{:#o}">(SV("0777777777777777777777"), std::numeric_limits<int64_t>::max());
check.template operator()<"{:#}">(SV("9223372036854775807"), std::numeric_limits<int64_t>::max());
check.template operator()<"{:#x}">(SV("0x7fffffffffffffff"), std::numeric_limits<int64_t>::max());
#ifndef TEST_HAS_NO_INT128
check.template operator()<"{:#b}">(
SV("0b111111111111111111111111111111111111111111111111111111111111111"
"1111111111111111111111111111111111111111111111111111111111111111"),
std::numeric_limits<__int128_t>::max());
check.template
operator()<"{:#o}">(SV("01777777777777777777777777777777777777777777"), std::numeric_limits<__int128_t>::max());
check.template
operator()<"{:#}">(SV("170141183460469231731687303715884105727"), std::numeric_limits<__int128_t>::max());
check.template operator()<"{:#x}">(SV("0x7fffffffffffffffffffffffffffffff"), std::numeric_limits<__int128_t>::max());
#endif
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_unsigned_integer(TestFunction check, ExceptionTest check_exception) {
format_test_integer<unsigned char, CharT>(check, check_exception);
format_test_integer<unsigned short, CharT>(check, check_exception);
format_test_integer<unsigned, CharT>(check, check_exception);
format_test_integer<unsigned long, CharT>(check, check_exception);
format_test_integer<unsigned long long, CharT>(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<uint8_t>::max());
check.template operator()<"{:#o}">(SV("0377"), std::numeric_limits<uint8_t>::max());
check.template operator()<"{:#}">(SV("255"), std::numeric_limits<uint8_t>::max());
check.template operator()<"{:#x}">(SV("0xff"), std::numeric_limits<uint8_t>::max());
check.template operator()<"{:#b}">(SV("0b1111111111111111"), std::numeric_limits<uint16_t>::max());
check.template operator()<"{:#o}">(SV("0177777"), std::numeric_limits<uint16_t>::max());
check.template operator()<"{:#}">(SV("65535"), std::numeric_limits<uint16_t>::max());
check.template operator()<"{:#x}">(SV("0xffff"), std::numeric_limits<uint16_t>::max());
check.template operator()<"{:#b}">(SV("0b11111111111111111111111111111111"), std::numeric_limits<uint32_t>::max());
check.template operator()<"{:#o}">(SV("037777777777"), std::numeric_limits<uint32_t>::max());
check.template operator()<"{:#}">(SV("4294967295"), std::numeric_limits<uint32_t>::max());
check.template operator()<"{:#x}">(SV("0xffffffff"), std::numeric_limits<uint32_t>::max());
check.template operator()<"{:#b}">(SV("0b1111111111111111111111111111111111111111111111111111111111111111"),
std::numeric_limits<uint64_t>::max());
check.template operator()<"{:#o}">(SV("01777777777777777777777"), std::numeric_limits<uint64_t>::max());
check.template operator()<"{:#}">(SV("18446744073709551615"), std::numeric_limits<uint64_t>::max());
check.template operator()<"{:#x}">(SV("0xffffffffffffffff"), std::numeric_limits<uint64_t>::max());
#ifndef TEST_HAS_NO_INT128
check.template operator()<"{:#b}">(
SV("0b1111111111111111111111111111111111111111111111111111111111111111"
"1111111111111111111111111111111111111111111111111111111111111111"),
std::numeric_limits<__uint128_t>::max());
check.template
operator()<"{:#o}">(SV("03777777777777777777777777777777777777777777"), std::numeric_limits<__uint128_t>::max());
check.template
operator()<"{:#}">(SV("340282366920938463463374607431768211455"), std::numeric_limits<__uint128_t>::max());
check.template operator()<"{:#x}">(SV("0xffffffffffffffffffffffffffffffff"), std::numeric_limits<__uint128_t>::max());
#endif
}
template <class CharT, class TestFunction, class ExceptionTest>
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<CharT>("bBcdoxX"))
check_exception("The format-spec type has a type not supported for a char argument", fmt, CharT('*'));
}
template <class CharT, class TestFunction, class ExceptionTest>
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<CharT>("bBcdoxX"))
check_exception("The format-spec type has a type not supported for a char argument", fmt, '*');
}
template <class F, class CharT, class TestFunction>
void format_test_floating_point_hex_lower_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6a}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6a}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7a}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7a}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7a}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-a}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+a}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: a}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010a}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010a}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010a}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010a}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010a}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010a}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010a}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_hex_upper_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6A}'">(SV("answer is 'INF***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6A}'">(SV("answer is '*INF**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7A}'">(SV("answer is '###-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7A}'">(SV("answer is '-INF###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7A}'">(SV("answer is '#-INF##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-A}'">(SV("answer is 'INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+A}'">(SV("answer is '+INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: A}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010A}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010A}'">(SV("answer is ' +INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010A}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010A}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010A}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010A}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010A}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_hex_lower_case_precision(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6.6a}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6.6a}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7.6a}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7.6a}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7.6a}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-.6a}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+.6a}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: .6a}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:.6a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-.6a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+.6a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: .6a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#.6a}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010.6a}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010.6a}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010.6a}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010.6a}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010.6a}'">(SV("answer is ' -inf'"),
-std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010.6a}'">(SV("answer is ' -inf'"),
-std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010.6a}'">(SV("answer is ' -inf'"),
-std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_hex_upper_case_precision(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6.6A}'">(SV("answer is 'INF***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6.6A}'">(SV("answer is '*INF**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7.6A}'">(SV("answer is '###-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7.6A}'">(SV("answer is '-INF###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7.6A}'">(SV("answer is '#-INF##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-.6A}'">(SV("answer is 'INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+.6A}'">(SV("answer is '+INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: .6A}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:.6A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-.6A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+.6A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: .6A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#.6A}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010.6A}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010.6A}'">(SV("answer is ' +INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010.6A}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010.6A}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010.6A}'">(SV("answer is ' -INF'"),
-std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010.6A}'">(SV("answer is ' -INF'"),
-std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010.6A}'">(SV("answer is ' -INF'"),
-std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_scientific_lower_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6e}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6e}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7e}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7e}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7e}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-e}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+e}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: e}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:e}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-e}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+e}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: e}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#e}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010e}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010e}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010e}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010e}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010e}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010e}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010e}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_scientific_upper_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6E}'">(SV("answer is 'INF***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6E}'">(SV("answer is '*INF**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7E}'">(SV("answer is '###-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7E}'">(SV("answer is '-INF###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7E}'">(SV("answer is '#-INF##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-E}'">(SV("answer is 'INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+E}'">(SV("answer is '+INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: E}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:E}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-E}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+E}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: E}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#E}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010E}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010E}'">(SV("answer is ' +INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010E}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010E}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010E}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010E}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010E}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_fixed_lower_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6f}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6f}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7f}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7f}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7f}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-f}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+f}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: f}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:f}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-f}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+f}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: f}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#f}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010f}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010f}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010f}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010f}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010f}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010f}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010f}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_fixed_upper_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6F}'">(SV("answer is 'INF***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6F}'">(SV("answer is '*INF**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7F}'">(SV("answer is '###-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7F}'">(SV("answer is '-INF###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7F}'">(SV("answer is '#-INF##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-F}'">(SV("answer is 'INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+F}'">(SV("answer is '+INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: F}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:F}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-F}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+F}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: F}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#F}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010F}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010F}'">(SV("answer is ' +INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010F}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010F}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010F}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010F}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010F}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_general_lower_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6g}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6g}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7g}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7g}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7g}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-g}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+g}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: g}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:g}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-g}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+g}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: g}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#g}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010g}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010g}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010g}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010g}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010g}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010g}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010g}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_general_upper_case(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6G}'">(SV("answer is 'INF***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6G}'">(SV("answer is '*INF**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7G}'">(SV("answer is '###-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7G}'">(SV("answer is '-INF###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7G}'">(SV("answer is '#-INF##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-G}'">(SV("answer is 'INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+G}'">(SV("answer is '+INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: G}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:G}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-G}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+G}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: G}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#G}'">(SV("answer is '-INF'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010G}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010G}'">(SV("answer is ' +INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010G}'">(SV("answer is ' INF'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010G}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010G}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010G}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010G}'">(SV("answer is ' -INF'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_default(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: }'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: }'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
void format_test_floating_point_default_precision(TestFunction check) {
auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
auto nan_neg = std::copysign(nan_pos, static_cast<decltype(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<F>::infinity());
check.template operator()<"answer is '{:*<6.6}'">(SV("answer is 'inf***'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:*^6.6}'">(SV("answer is '*inf**'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#>7.6}'">(SV("answer is '###-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#<7.6}'">(SV("answer is '-inf###'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:#^7.6}'">(SV("answer is '#-inf##'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-.6}'">(SV("answer is 'inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+.6}'">(SV("answer is '+inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: .6}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:.6}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-.6}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+.6}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: .6}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:#.6}'">(SV("answer is '-inf'"), -std::numeric_limits<F>::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<F>::infinity());
check.template operator()<"answer is '{:-010.6}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010.6}'">(SV("answer is ' +inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010.6}'">(SV("answer is ' inf'"), std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:-010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{:+010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::infinity());
check.template operator()<"answer is '{: 010.6}'">(SV("answer is ' -inf'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction, class ExceptionTest>
void format_test_floating_point(TestFunction check, ExceptionTest check_exception) {
format_test_floating_point_hex_lower_case<F, CharT>(check);
format_test_floating_point_hex_upper_case<F, CharT>(check);
format_test_floating_point_hex_lower_case_precision<F, CharT>(check);
format_test_floating_point_hex_upper_case_precision<F, CharT>(check);
format_test_floating_point_scientific_lower_case<F, CharT>(check);
format_test_floating_point_scientific_upper_case<F, CharT>(check);
format_test_floating_point_fixed_lower_case<F, CharT>(check);
format_test_floating_point_fixed_upper_case<F, CharT>(check);
format_test_floating_point_general_lower_case<F, CharT>(check);
format_test_floating_point_general_upper_case<F, CharT>(check);
format_test_floating_point_default<F, CharT>(check);
format_test_floating_point_default_precision<F, CharT>(check);
// *** type ***
for (const auto& fmt : invalid_types<CharT>("aAeEfFgG"))
check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, F(1));
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_floating_point(TestFunction check, ExceptionTest check_exception) {
format_test_floating_point<float, CharT>(check, check_exception);
format_test_floating_point<double, CharT>(check, check_exception);
format_test_floating_point<long double, CharT>(check, check_exception);
}
template <class P, class CharT, class TestFunction, class ExceptionTest>
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<CharT>("p"))
check_exception("The format-spec type has a type not supported for a pointer argument", fmt, P(nullptr));
}
template <class CharT, class TestFunction, class ExceptionTest>
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);
// P2418 Changed the argument from a const reference to a forwarding reference.
// This mainly affects handle classes, however since we use an abstraction
// layer here it's "tricky" to verify whether this test would do the "right"
// thing. So these tests are done separately.
// *** type ***
for (const auto& fmt : invalid_types<CharT>("xXs"))
check_exception("The format-spec type has a type not supported for a status argument", fmt, status::foo);
}
template <class CharT, class TestFunction, class ExceptionTest>
void format_test_pointer(TestFunction check, ExceptionTest check_exception) {
format_test_pointer<std::nullptr_t, CharT>(check, check_exception);
format_test_pointer<void*, CharT>(check, check_exception);
format_test_pointer<const void*, CharT>(check, check_exception);
}
template <class CharT, class TestFunction, class ExceptionTest>
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<CharT>(check, check_exception);
format_test_char_as_integer<CharT>(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<CharT> data = STR("world");
check.template operator()<"hello {}">(SV("hello world"), data);
}
{
std::basic_string<CharT> buffer = STR("world");
std::basic_string_view<CharT> data = buffer;
check.template operator()<"hello {}">(SV("hello world"), data);
}
format_string_tests<CharT>(check, check_exception);
// *** Test Boolean format argument ***
check.template operator()<"hello {} {}">(SV("hello false true"), false, true);
format_test_bool<CharT>(check, check_exception);
format_test_bool_as_integer<CharT>(check, check_exception);
// *** Test signed integral format argument ***
check.template operator()<"hello {}">(SV("hello 42"), static_cast<signed char>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<short>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<int>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<long>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<long long>(42));
#ifndef TEST_HAS_NO_INT128
check.template operator()<"hello {}">(SV("hello 42"), static_cast<__int128_t>(42));
#endif
format_test_signed_integer<CharT>(check, check_exception);
// ** Test unsigned integral format argument ***
check.template operator()<"hello {}">(SV("hello 42"), static_cast<unsigned char>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<unsigned short>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<unsigned>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<unsigned long>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<unsigned long long>(42));
#ifndef TEST_HAS_NO_INT128
check.template operator()<"hello {}">(SV("hello 42"), static_cast<__uint128_t>(42));
#endif
format_test_unsigned_integer<CharT>(check, check_exception);
// *** Test floating point format argument ***
check.template operator()<"hello {}">(SV("hello 42"), static_cast<float>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<double>(42));
check.template operator()<"hello {}">(SV("hello 42"), static_cast<long double>(42));
format_test_floating_point<CharT>(check, check_exception);
// *** Test pointer formater argument ***
check.template operator()<"hello {}">(SV("hello 0x0"), nullptr);
check.template operator()<"hello {}">(SV("hello 0x42"), reinterpret_cast<void*>(0x42));
check.template operator()<"hello {}">(SV("hello 0x42"), reinterpret_cast<const void*>(0x42));
format_test_pointer<CharT>(check, check_exception);
// *** Test handle formatter argument ***
format_test_handle<CharT>(check, check_exception);
}
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
template <class TestFunction>
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