Skip to content

Commit 785e094

Browse files
authored
[libc++] Fix incomplete user-defined ctype specialization in test (#74630)
The specialization was non-conforming because it was missing a bunch of member functions. Those were missing probably just as an oversight coupled with a bit of laziness -- the rule that user-defined specializations need to match the base template is usually OK to take with a grain of salt, but not when the code is supposed to be portable, which our test suite aims to be. Fixes #74214
1 parent 26fbdff commit 785e094

File tree

1 file changed

+44
-8
lines changed

1 file changed

+44
-8
lines changed

libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/user_defined_char_type.pass.cpp

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include <locale>
1717
#include <string>
1818

19-
#include "test_macros.h"
20-
2119
struct Char {
2220
Char() = default;
2321
Char(char c) : underlying_(c) {}
@@ -73,15 +71,53 @@ struct char_traits<Char> {
7371
static int_type eof() { return char_traits<char>::eof(); }
7472
};
7573

74+
// This ctype specialization treats all characters as spaces
7675
template <>
77-
class ctype<Char> : public locale::facet {
76+
class ctype<Char> : public locale::facet, public ctype_base {
7877
public:
78+
using char_type = Char;
7979
static locale::id id;
80-
Char toupper(Char c) const { return Char(std::toupper(c.underlying_)); }
81-
const char* widen(const char* first, const char* last, Char* dst) const {
82-
for (; first != last;)
83-
*dst++ = Char(*first++);
84-
return last;
80+
explicit ctype(std::size_t refs = 0) : locale::facet(refs) {}
81+
82+
bool is(mask m, char_type) const { return m & ctype_base::space; }
83+
const char_type* is(const char_type* low, const char_type* high, mask* vec) const {
84+
for (; low != high; ++low)
85+
*vec++ = ctype_base::space;
86+
return high;
87+
}
88+
89+
const char_type* scan_is(mask m, const char_type* beg, const char_type* end) const {
90+
for (; beg != end; ++beg)
91+
if (this->is(m, *beg))
92+
return beg;
93+
return end;
94+
}
95+
96+
const char_type* scan_not(mask m, const char_type* beg, const char_type* end) const {
97+
for (; beg != end; ++beg)
98+
if (!this->is(m, *beg))
99+
return beg;
100+
return end;
101+
}
102+
103+
char_type toupper(char_type c) const { return c; }
104+
const char_type* toupper(char_type*, const char_type* end) const { return end; }
105+
106+
char_type tolower(char_type c) const { return c; }
107+
const char_type* tolower(char_type*, const char_type* end) const { return end; }
108+
109+
char_type widen(char c) const { return char_type(c); }
110+
const char* widen(const char* beg, const char* end, char_type* dst) const {
111+
for (; beg != end; ++beg, ++dst)
112+
*dst = char_type(*beg);
113+
return end;
114+
}
115+
116+
char narrow(char_type c, char /*dflt*/) const { return c.underlying_; }
117+
const char_type* narrow(const char_type* beg, const char_type* end, char /*dflt*/, char* dst) const {
118+
for (; beg != end; ++beg, ++dst)
119+
*dst = beg->underlying_;
120+
return end;
85121
}
86122
};
87123

0 commit comments

Comments
 (0)