[libcxx-dev] std::ctype, std::numpunct base templates

James Skene via libcxx-dev libcxx-dev at lists.llvm.org
Tue Aug 4 16:33:05 PDT 2020


On Wed, 5 Aug 2020 at 10:18, Marshall Clow <mclow.lists at gmail.com> wrote:

>
>
> On Aug 4, 2020, at 2:41 PM, James Skene <j.skene at gmail.com> wrote:
>
>
> On Wed, 5 Aug 2020 at 02:41, Marshall Clow <mclow.lists at gmail.com> wrote:
>
>>
>>
>> On Aug 4, 2020, at 12:57 AM, James Skene <j.skene at gmail.com> wrote:
>>
>> Hi Marshall,
>>
>> Thanks for your prompt response.  I have some follow-ups below.  I hope
>> you don't object to me pursuing this a little bit.
>>
>> On Tue, 4 Aug 2020 at 17:30, Marshall Clow <mclow.lists at gmail.com> wrote:
>>
>>> On Aug 3, 2020, at 8:25 PM, James Skene via libcxx-dev <
>>> libcxx-dev at lists.llvm.org> wrote:
>>> >
>>> > Hi,
>>> >
>>> > I'm considering submitting a bug report against libc++, but thought I
>>> would check here first.
>>> >
>>> > The standard gives a synopsis for the locale facet std::ctype<CharT>
>>> in Section 25.4.1 (C++17, but it is also in C++11), and
>>> std::numpunct<CharT> in Section 25.4.3.  Under libc++ specialisations of
>>> these templates are defined for char and wchar_t (in header '__locale') but
>>> the base template definition is omitted.  This means in particular that I
>>> cannot define:
>>> >
>>> > class my_ctype : public std::ctype<char16_t> { ... };
>>> >
>>> > class my_numpunct : public std::numpunct<char16_t> { ... };
>>>
>>> Yes, I believe that this is correct.
>>>
>>> > This seems to go against the intent of these classes, which include
>>> abstract virtual function declarations.  Although clause 30.2.2 restricts
>>> the support for stream-based I/O that an implementation must provide to the
>>> types char and wchar_t, it is not clear to me that this means the
>>> definitions of the above templates can be omitted.
>>> >
>>> > I would appreciate advice as to: a. whether this is actually an issue
>>> or my misreading of the spec; and b. if so, if it is a known issue.
>>>
>>> https://wg21.link/locale.category lists the required specializations
>>> for numpunct and ctype.
>>>
>>> It doesn’t say anything about the general template.
>>>
>>> So, I would say this is not a bug.
>>>
>>
>> Does it, anywhere in the specification, state that where required
>> specialisations are listed, the need to implement the general template is
>> removed?
>>
>> There seems to be no such statement in Section 20.5.5.2 Conforming
>> Implementations.  On the other hand 20.5.2.2.1 states:
>>
>> A C++ header shall provide the declarations and definitions that appear
>> in its synopsis.
>>
>>
>>> From an implementation point of view, the implementations of ctype<char>
>>> and type<wchar_t> are fairly different, and have a lot of system -specific
>>> knowledge baked into them. I don’t think I really know enough about
>>> charXX_t (8/16/32) on various systems to provide high-quality
>>> implementations (and in the case of char32_t, in a reasonable size of
>>> code/data). ICU does much of this, but it’s quite large.
>>>
>>>
>> I think there is a problem with the way the specification is written in
>> this instance.  The virtual functions in the base class should really be
>> pure virtual and the descriptions given of their (general) behaviour should
>> be requirements on subclasses or specialisations.  GCC and Visual Studio
>> both implement these functions by casting (or trying to narrow) their
>> character arguments to char.  GCCs inline documentation states
>> 'implementations are provided for all the protected virtual functions, but
>> will likely not be useful'.  That said, bearing in mind that the ctype
>> functionality only applies to characters in the basic execution character
>> set, which are usually 7-bit ASCII (invariant) characters, this is probably
>> a reasonable choice.  Another choice, and perhaps no more nonstandard than
>> simply omitting the base class, would be to implement these functions as
>> assertion failures.
>>
>> I agree that, notwithstanding the way the specification is written, it is
>> unreasonable to expect implementers to provide useful implementations for
>> more than the required specialisations.  But actually I do not want a
>> useful implementation, just the opportunity to override a virtual function.
>> As it happens my goal is specifically to extend ctype, numpunct, and the
>> other facets to implement the functionality using ICU.  I would prefer this
>> work to be portable to clang.
>>
>>
>> When  you try to do this:
>> class my_numpunct : public std::numpunct<char16_t> { ... };
>>
>> You are depending on the existence of `numpunct<char16_t>`. (Whether as
>> an explicit class, or via the general template).
>> And that’s not something that the standard insists upon.
>>
>> So I don’t see how you can do this portably.
>>
>> — Marshall
>>
>
> The general templates would be declared as per the spec.  The member
> functions would be defined something like this:
>
>
> Sure, they *could* be defined something like that.
> But my point is that a conforming implementation need not have
> `numpunct<char16_t>` at all.
>
> — Marshall
>
>
And that comes down to the interpretation of the specification.  Your
position, as I understand it, is that the specification does not require
the general template to be defined.  But I don't see the justification for
that in the letter of the specification.  And neither is this the position
that GCC or Visual Studio take.  So what am I failing to understand?

J.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/libcxx-dev/attachments/20200805/56e394c0/attachment-0001.html>


More information about the libcxx-dev mailing list