Skip to content

Commit 7a073e3

Browse files
mordantecopybara-github
authored andcommitted
[libc++][chrono] Fixes (sys|local)_time formatters. (#76456)
- The sys_time formatter is constrained, which was not implemented. - There is a sys_days formatter which was not implemented. - The local_time formatter uses the sys_time formatter in its implementation so "inherited" the same issues. Fixes: llvm/llvm-project#73849 Fixes: llvm/llvm-project#67983 NOKEYCHECK=True GitOrigin-RevId: 042a6a1349d512edaaa225380771c64a8d92810a
1 parent 7a13de8 commit 7a073e3

File tree

6 files changed

+314
-58
lines changed

6 files changed

+314
-58
lines changed

include/__chrono/ostream.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD
4242
namespace chrono {
4343

4444
template <class _CharT, class _Traits, class _Duration>
45+
requires(!treat_as_floating_point_v<typename _Duration::rep> && _Duration{1} < days{1})
4546
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
46-
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_time<_Duration> __tp) {
47+
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_time<_Duration>& __tp) {
4748
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
4849
}
4950

51+
template <class _CharT, class _Traits>
52+
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
53+
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp) {
54+
return __os << year_month_day{__dp};
55+
}
56+
5057
template <class _CharT, class _Traits, class _Duration>
5158
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
5259
operator<<(basic_ostream<_CharT, _Traits>& __os, const file_time<_Duration> __tp) {

include/chrono

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ template<class charT, class traits, class Duration> // C++20
296296
basic_ostream<charT, traits>&
297297
operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp);
298298
299+
template<class charT, class traits> // C++20
300+
basic_ostream<charT, traits>&
301+
operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);
302+
299303
class file_clock // C++20
300304
{
301305
public:

test/std/time/time.clock/time.clock.local/ostream.pass.cpp

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,11 @@ static void test_c() {
7575
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::minutes>{20'576'131min}) ==
7676
SV("2009-02-13 23:31:00"));
7777
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::hours>{342'935h}) == SV("2009-02-13 23:00:00"));
78-
assert(stream_c_locale<CharT>(std::chrono::local_days{std::chrono::days{14'288}}) == SV("2009-02-13 00:00:00"));
78+
79+
// These switch to sys_day formatter, which omits the time.
80+
assert(stream_c_locale<CharT>(std::chrono::local_days{std::chrono::days{14'288}}) == SV("2009-02-13"));
7981
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::weeks>{std::chrono::weeks{2041}}) ==
80-
SV("2009-02-12 00:00:00"));
82+
SV("2009-02-12"));
8183

8284
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::duration<signed char, std::ratio<2, 1>>>{
8385
std::chrono::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1970-01-01 00:02:00"));
@@ -89,13 +91,6 @@ static void test_c() {
8991
std::chrono::duration<long, std::ratio<1, 10>>{36611}}) == SV("1970-01-01 01:01:01.1"));
9092
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::duration<long long, std::ratio<1, 100>>>{
9193
std::chrono::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("2009-02-13 23:31:30.10"));
92-
93-
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::duration<float, std::ratio<1, 1>>>{
94-
std::chrono::duration<float, std::ratio<1, 1>>{123.456}}) == SV("1970-01-01 00:02:03"));
95-
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::duration<double, std::ratio<1, 10>>>{
96-
std::chrono::duration<double, std::ratio<1, 10>>{123.456}}) == SV("1970-01-01 00:00:12.3"));
97-
assert(stream_c_locale<CharT>(std::chrono::local_time<std::chrono::duration<long double, std::ratio<1, 100>>>{
98-
std::chrono::duration<long double, std::ratio<1, 100>>{123.456}}) == SV("1970-01-01 00:00:01.23"));
9994
}
10095

10196
template <class CharT>
@@ -114,9 +109,11 @@ static void test_fr_FR() {
114109
SV("2009-02-13 23:31:00"));
115110
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::hours>{342'935h}) ==
116111
SV("2009-02-13 23:00:00"));
117-
assert(stream_fr_FR_locale<CharT>(std::chrono::local_days{std::chrono::days{14'288}}) == SV("2009-02-13 00:00:00"));
112+
113+
// These switch to sys_day formatter, which omits the time.
114+
assert(stream_fr_FR_locale<CharT>(std::chrono::local_days{std::chrono::days{14'288}}) == SV("2009-02-13"));
118115
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::weeks>{std::chrono::weeks{2041}}) ==
119-
SV("2009-02-12 00:00:00"));
116+
SV("2009-02-12"));
120117

121118
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::duration<signed char, std::ratio<2, 1>>>{
122119
std::chrono::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1970-01-01 00:02:00"));
@@ -128,13 +125,6 @@ static void test_fr_FR() {
128125
std::chrono::duration<long, std::ratio<1, 10>>{36611}}) == SV("1970-01-01 01:01:01,1"));
129126
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::duration<long long, std::ratio<1, 100>>>{
130127
std::chrono::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("2009-02-13 23:31:30,10"));
131-
132-
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::duration<float, std::ratio<1, 1>>>{
133-
std::chrono::duration<float, std::ratio<1, 1>>{123.456}}) == SV("1970-01-01 00:02:03"));
134-
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::duration<double, std::ratio<1, 10>>>{
135-
std::chrono::duration<double, std::ratio<1, 10>>{123.456}}) == SV("1970-01-01 00:00:12,3"));
136-
assert(stream_fr_FR_locale<CharT>(std::chrono::local_time<std::chrono::duration<long double, std::ratio<1, 100>>>{
137-
std::chrono::duration<long double, std::ratio<1, 100>>{123.456}}) == SV("1970-01-01 00:00:01,23"));
138128
}
139129

140130
template <class CharT>
@@ -153,9 +143,11 @@ static void test_ja_JP() {
153143
SV("2009-02-13 23:31:00"));
154144
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::hours>{342'935h}) ==
155145
SV("2009-02-13 23:00:00"));
156-
assert(stream_ja_JP_locale<CharT>(std::chrono::local_days{std::chrono::days{14'288}}) == SV("2009-02-13 00:00:00"));
146+
147+
// These switch to sys_day formatter, which omits the time.
148+
assert(stream_ja_JP_locale<CharT>(std::chrono::local_days{std::chrono::days{14'288}}) == SV("2009-02-13"));
157149
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::weeks>{std::chrono::weeks{2041}}) ==
158-
SV("2009-02-12 00:00:00"));
150+
SV("2009-02-12"));
159151

160152
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::duration<signed char, std::ratio<2, 1>>>{
161153
std::chrono::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1970-01-01 00:02:00"));
@@ -167,13 +159,6 @@ static void test_ja_JP() {
167159
std::chrono::duration<long, std::ratio<1, 10>>{36611}}) == SV("1970-01-01 01:01:01.1"));
168160
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::duration<long long, std::ratio<1, 100>>>{
169161
std::chrono::duration<long long, std::ratio<1, 100>>{12'345'678'9010}}) == SV("2009-02-13 23:31:30.10"));
170-
171-
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::duration<float, std::ratio<1, 1>>>{
172-
std::chrono::duration<float, std::ratio<1, 1>>{123.456}}) == SV("1970-01-01 00:02:03"));
173-
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::duration<double, std::ratio<1, 10>>>{
174-
std::chrono::duration<double, std::ratio<1, 10>>{123.456}}) == SV("1970-01-01 00:00:12.3"));
175-
assert(stream_ja_JP_locale<CharT>(std::chrono::local_time<std::chrono::duration<long double, std::ratio<1, 100>>>{
176-
std::chrono::duration<long double, std::ratio<1, 100>>{123.456}}) == SV("1970-01-01 00:00:01.23"));
177162
}
178163

179164
template <class CharT>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: no-localization
11+
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
12+
13+
// TODO FMT This test should not require std::to_chars(floating-point)
14+
// XFAIL: availability-fp_to_chars-missing
15+
16+
// <chrono>
17+
18+
// class system_clock;
19+
20+
// template<class charT, class traits, class Duration>
21+
// basic_ostream<charT, traits>&
22+
// operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& tp);
23+
24+
// The function uses the system_clock which has two overloads
25+
26+
// template<class charT, class traits, class Duration>
27+
// basic_ostream<charT, traits>&
28+
// operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp);
29+
// Constraints: treat_as_floating_point_v<typename Duration::rep> is false, and Duration{1} < days{1} is true.
30+
31+
// template<class charT, class traits>
32+
// basic_ostream<charT, traits>&
33+
// operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);
34+
35+
// Note local_time's operator<< is specified a
36+
// Effects: os << sys_time<Duration>{lt.time_since_epoch()};
37+
// since it uses Effects and not Effects: Equivalent to the constrains of
38+
// sys_time do not apply to this operator. This means it's not possible to use
39+
// a SFINAE test.
40+
41+
#include <chrono>
42+
#include <ratio>
43+
#include <sstream>
44+
#include <type_traits>
45+
46+
void test() {
47+
std::stringstream sstr;
48+
49+
// floating-point values
50+
51+
sstr << // expected-error@*:* {{invalid operands to binary expression}}
52+
std::chrono::local_time<std::chrono::duration<float, std::ratio<1, 1>>>{
53+
std::chrono::duration<float, std::ratio<1, 1>>{0}};
54+
55+
sstr << // expected-error@*:* {{invalid operands to binary expression}}
56+
std::chrono::local_time<std::chrono::duration<double, std::ratio<1, 1>>>{
57+
std::chrono::duration<double, std::ratio<1, 1>>{0}};
58+
59+
sstr << // expected-error@*:* {{invalid operands to binary expression}}
60+
std::chrono::local_time<std::chrono::duration<long double, std::ratio<1, 1>>>{
61+
std::chrono::duration<long double, std::ratio<1, 1>>{0}};
62+
63+
// duration >= day
64+
65+
sstr << // valid since day has its own formatter
66+
std::chrono::local_days{std::chrono::days{0}};
67+
68+
using rep = std::conditional_t<std::is_same_v<std::chrono::days::rep, int>, long, int>;
69+
sstr << // a different rep does not matter,
70+
std::chrono::local_time<std::chrono::duration<rep, std::ratio<86400>>>{
71+
std::chrono::duration<rep, std::ratio<86400>>{0}};
72+
73+
sstr << // expected-error@*:* {{invalid operands to binary expression}}
74+
std::chrono::local_time<std::chrono::duration<typename std::chrono::days::rep, std::ratio<86401>>>{
75+
std::chrono::duration<typename std::chrono::days::rep, std::ratio<86401>>{0}};
76+
77+
sstr << // These are considered days.
78+
std::chrono::local_time<std::chrono::weeks>{std::chrono::weeks{3}};
79+
80+
sstr << // These too.
81+
std::chrono::local_time<std::chrono::duration<rep, std::ratio<20 * 86400>>>{
82+
std::chrono::duration<rep, std::ratio<20 * 86400>>{0}};
83+
84+
sstr << // expected-error@*:* {{invalid operands to binary expression}}
85+
std::chrono::local_time<std::chrono::months>{std::chrono::months{0}};
86+
87+
sstr << // expected-error@*:* {{invalid operands to binary expression}}
88+
std::chrono::local_time<std::chrono::years>{std::chrono::years{0}};
89+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
// UNSUPPORTED: no-localization
11+
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
12+
13+
// TODO FMT This test should not require std::to_chars(floating-point)
14+
// XFAIL: availability-fp_to_chars-missing
15+
16+
// TODO FMT Investigate Windows issues.
17+
// XFAIL: msvc
18+
19+
// REQUIRES: locale.fr_FR.UTF-8
20+
// REQUIRES: locale.ja_JP.UTF-8
21+
22+
// <chrono>
23+
24+
// class system_Clock;
25+
26+
// template<class charT, class traits>
27+
// basic_ostream<charT, traits>&
28+
// operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);
29+
30+
#include <cassert>
31+
#include <chrono>
32+
#include <ratio>
33+
#include <sstream>
34+
35+
#include "make_string.h"
36+
#include "platform_support.h" // locale name macros
37+
#include "test_macros.h"
38+
#include "assert_macros.h"
39+
#include "concat_macros.h"
40+
41+
#define SV(S) MAKE_STRING_VIEW(CharT, S)
42+
43+
#define TEST_EQUAL(OUT, EXPECTED) \
44+
TEST_REQUIRE(OUT == EXPECTED, \
45+
TEST_WRITE_CONCATENATED( \
46+
"\nExpression ", #OUT, "\nExpected output ", EXPECTED, "\nActual output ", OUT, '\n'));
47+
48+
template <class CharT>
49+
static std::basic_string<CharT> stream_c_locale(const std::chrono::sys_days& dp) {
50+
std::basic_stringstream<CharT> sstr;
51+
sstr << dp;
52+
return sstr.str();
53+
}
54+
55+
template <class CharT>
56+
static std::basic_string<CharT> stream_fr_FR_locale(const std::chrono::sys_days& dp) {
57+
std::basic_stringstream<CharT> sstr;
58+
const std::locale locale(LOCALE_fr_FR_UTF_8);
59+
sstr.imbue(locale);
60+
sstr << dp;
61+
return sstr.str();
62+
}
63+
64+
template <class CharT>
65+
static std::basic_string<CharT> stream_ja_JP_locale(const std::chrono::sys_days& dp) {
66+
std::basic_stringstream<CharT> sstr;
67+
const std::locale locale(LOCALE_ja_JP_UTF_8);
68+
sstr.imbue(locale);
69+
sstr << dp;
70+
return sstr.str();
71+
}
72+
73+
template <class CharT>
74+
static void test() {
75+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
76+
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}}),
77+
SV("-32768-01-01 is not a valid date"));
78+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
79+
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}}),
80+
SV("1970-01-01"));
81+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
82+
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
83+
SV("2000-02-29"));
84+
85+
#if defined(_AIX)
86+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
87+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
88+
SV("+32767-12-31"));
89+
#elif defined(_WIN32) // defined(_AIX)
90+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
91+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
92+
SV(""));
93+
#else // defined(_AIX)
94+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
95+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
96+
SV("32767-12-31"));
97+
#endif // defined(_AIX)
98+
99+
// multiples of days are considered days.
100+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
101+
SV("1970-01-22"));
102+
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::duration<int, std::ratio<30 * 86400>>>{
103+
std::chrono::duration<int, std::ratio<30 * 86400>>{1}}),
104+
SV("1970-01-31"));
105+
106+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
107+
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}}),
108+
SV("-32768-01-01 is not a valid date"));
109+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
110+
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}}),
111+
SV("1970-01-01"));
112+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
113+
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
114+
SV("2000-02-29"));
115+
#if defined(_AIX)
116+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
117+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
118+
SV("+32767-12-31"));
119+
#elif defined(_WIN32) // defined(_AIX)
120+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
121+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
122+
SV(""));
123+
#else // defined(_AIX)
124+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
125+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
126+
SV("32767-12-31"));
127+
#endif // defined(_AIX)
128+
129+
// multiples of days are considered days.
130+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
131+
SV("1970-01-22"));
132+
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::duration<int, std::ratio<30 * 86400>>>{
133+
std::chrono::duration<int, std::ratio<30 * 86400>>{1}}),
134+
SV("1970-01-31"));
135+
136+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
137+
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}}),
138+
SV("-32768-01-01 is not a valid date"));
139+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
140+
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{1}, std::chrono::day{1}}}),
141+
SV("1970-01-01"));
142+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
143+
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
144+
SV("2000-02-29"));
145+
#if defined(_AIX)
146+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
147+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
148+
SV("+32767-12-31"));
149+
#elif defined(_WIN32) // defined(_AIX)
150+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
151+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
152+
SV(""));
153+
#else // defined(_AIX)
154+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
155+
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
156+
SV("32767-12-31"));
157+
#endif // defined(_AIX)
158+
159+
// multiples of days are considered days.
160+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
161+
SV("1970-01-22"));
162+
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::duration<int, std::ratio<30 * 86400>>>{
163+
std::chrono::duration<int, std::ratio<30 * 86400>>{1}}),
164+
SV("1970-01-31"));
165+
}
166+
167+
int main(int, char**) {
168+
test<char>();
169+
170+
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
171+
test<wchar_t>();
172+
#endif
173+
174+
return 0;
175+
}

0 commit comments

Comments
 (0)