Topic: [Fwd: Inconsistencies in the interface of locale]


Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 7 May 2003 09:34:16 +0000 (UTC)
Raw View
sebor@roguewave.com (Martin Sebor) wrote in message
news:<3EB6F820.3060204@roguewave.com>...
> James Kanze wrote:
> ...
> >>There are implementations out there that fail to accept a const T*
> >>as the second argument to the template ctor, but those are, IMHO,
> >>buggy. Our latest implementation, and recent versions of GNU
> >>libstdc++ accept a const T* in this context.

> > Strange.  I discovered the problem as the result of a compiler
> > error.  From g++ 3.2.2.

> > You seem to talk as if it were a library issue.

> I don't think it is,=20

I meant issue in the sense of problem or bug, not in the sense of a
standards library issue.  If the signature is not what we want, of
course, it is a standards library issue, but for the moment, I think
that is up in air.

Basically, I'm confusing two things.  I noticed the difference in the
const when looking up the functions to use them.  I considered the
possibility that Facet could resolve to something const, and tried it.
I got a compiler error.  I didn't look further; I supposed that it was
the same type of error that I have gotten before, with things like:

    template< typename T, size_t N >
    T*
    begin( T (&array)[ N ] )
    {
        return array ;
    }

This doesn't compile when passed a const array.  I don't know why, but
it doesn't.  Providing a second version with const works.  I don't know
why; I would have expected conflicts.

I've just recompiled my test (without the const_cast).  The error IS in
the instantiation, so it is, as you say, an error in the library
implementation.

    [...]
> > I'll admit that I'm still a bit up in the air about this.  There is
> > no way for a user to obtain a non-const pointer or reference to a
> > facet from a locale.  None of the derived interfaces of
> > locale::facet have any non-const functions.  I presume that the lack
> > of const is due to the implicit reference counting in facet (
> > 22.1.1.1.2/3).  If this is really the case, of course, the reference
> > counting won't work if Facet resolves to a const type, unless the
> > implementation uses a const cast or a mutable member in
> > locale::facet.  If the implementation uses const cast or a mutable
> > member, there is no reason why the template should not take a Facet
> > const*.  If it doesn't, then the implementation won't work with a
> > const pointer anyway, so there is no reason why the template should
> > take a non const pointer either.

> To be perfectly honest, I think the usage you came up with (passing
> the result of use facet to the template ctor) may not have even been
> anticipated when C++ locale was designed (but I just speculate).

Strange.  It seems to me to be the most obvious use.  I mean, it's not
like just any, everyday programmer can write a Facet on his own.  (I
know that I've not been able to do so, myself.  And I suspect that there
are programmers out there less qualified than myself, who will find it
even more difficult.)

> The fact that the Facet template parameter binds to a const pointer
> may have very well been a coincidence. But the fact is that regardless
> of the intent, Facet* does bind to a const T making your use case
> legal and implementations that reject it non-conforming.

It might still be worth adding some sort of note to the effect, that
Facet uses conceptual const, and that the reference count in the base
class should be mutable.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.=
fr
Conseils en informatique orient=E9e objet/
                           Beratung in objektorientierter Datenverarbeitu=
ng
11 rue de Rambouillet, 78460 Chevreuse, France, T=E9l. : +33 (0)1 30 23 4=
5 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: sebor@roguewave.com (Martin Sebor)
Date: Tue, 6 May 2003 00:16:11 +0000 (UTC)
Raw View
James Kanze wrote:
...
>>There are implementations out there that fail to accept a const T* as
>>the second argument to the template ctor, but those are, IMHO,
>>buggy. Our latest implementation, and recent versions of GNU libstdc++
>>accept a const T* in this context.
>=20
>=20
> Strange.  I discovered the problem as the result of a compiler error.
>>From g++ 3.2.2.
>=20
> You seem to talk as if it were a library issue.

I don't think it is, but I have seen errors out of both the GNU
C++ Standard library and the Dinkum C++ Standard library (as well
as old releases of our implementation of the same), so I know that
implementations tend to have problems in this area. IIRC, I also
mentioned it to the GNU libstdc++ maintainers and I was under the
impression that they fixed it, but the fixes don't seem to have
made it into 3.2.2 (maybe 3.3 or 3.4?)

> The signatures are
> imposed by the standard, and should be the same in any library, no?

The signatures are the same, but the implementation of the function
template often assumes that the Facet template parameter is a non
const type (since the ctor must bump up the reference count of the
facet). One could argue that if the ctor must change the state of
the facet the Facet* pointer should not [allowed to] be const, but
I think the example you gave should provide sufficient motivation
to accept const Facet* as well. In any case, though, the current
standard does not forbid const Facet*, so unless an issue is opened
to prohibit it any implementation that rejects it violates the
standard :)

> And
> the compiler error was along the lines of not being able to find a matc=
h
> for the function, not from anything within the function.

I haven't seen the error message but SunPro issues such errors
because of limitations in their implementation of the C++ Standard
library. Here are errors from a few popular implementations:

GCC 3.2.2:
localefwd.h: In
    constructor `std::locale::locale(const std::locale&, _Facet*) [with=20
_Facet =3D const std::ctype<char>]':
t.cpp:9:   instantiated from here
localefwd.h:401: invalid
    conversion from `const std::locale::facet*' to `std::locale::facet*'
localefwd.h:401:
    initializing argument 2 of `void=20
std::locale::_Impl::_M_install_facet(const
    std::locale::id*, std::locale::facet*)'

HP aCC 3.39:
Error (future) 212: "rwlocale", line 559 # Argument type 'const=20
std::ctype<char> *' does not match expected parameter type=20
'__rw::__rw_facet_base *'.
             _C_install_facet (__facet, _Facet::id);
                               ^^^^^^^
IBM VAC++ 6.0:
"xlocale", line 177.40: 1540-0256 (S) A parameter of type=20
"std::locale::facet *" cannot be initialized with an expression of type=20
"const std::ctype<char> *".
"xlocale", line 177.40: 1540-1205 (I) The error occurred while=20
converting to parameter 1 of "std::locale::_Locimp::_Addfac(facet *,=20
size_t)".
"xlocale", line 174.17: 1540-0700 (I) The previous message was produced=20
while processing "std::locale::locale(const locale &, const ctype<char> *=
)".
"t.cpp", line 9.23: 1540-0700 (I) The previous message was produced=20
while processing "main()".

SunPro 5.5:
"t.cpp", line 7: Error: Could not find a match for=20
std::use_facet<std::Facet>(const std::locale).
"t.cpp", line 9: Error: Could not find a match for=20
std::locale::locale(const std::locale, const std::ctype<char>*).
2 Error(s) detected.

>=20
> I'll admit that I'm still a bit up in the air about this.  There is no
> way for a user to obtain a non-const pointer or reference to a facet
> from a locale.  None of the derived interfaces of locale::facet have an=
y
> non-const functions.  I presume that the lack of const is due to the
> implicit reference counting in facet (=A722.1.1.1.2/3).  If this is rea=
lly
> the case, of course, the reference counting won't work if Facet resolve=
s
> to a const type, unless the implementation uses a const_cast or a
> mutable member in locale::facet.  If the implementation uses const_cast
> or a mutable member, there is no reason why the template should not tak=
e
> a Facet const*.  If it doesn't, then the implementation won't work with
> a const pointer anyway, so there is no reason why the template should
> take a non const pointer either.

To be perfectly honest, I think the usage you came up with
(passing the result of use_facet to the template ctor) may
not have even been anticipated when C++ locale was designed
(but I just speculate). The fact that the Facet template
parameter binds to a const pointer may have very well been
a coincidence. But the fact is that regardless of the intent,
Facet* does bind to a const T making your use case legal and
implementations that reject it non-conforming.

Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: sebor@roguewave.com (Martin Sebor)
Date: Wed, 30 Apr 2003 22:54:32 +0000 (UTC)
Raw View
This was never posted (not delivered?)

-------- Original Message --------
Subject: Re: Inconsistencies in the interface of locale
Date: Mon, 28 Apr 2003 13:50:42 -0600
From: Martin Sebor <sebor@roguewave.com>
Organization: Rogue Wave Software, Inc.
Newsgroups: comp.std.c++
References: <d6651fb6.0304250415.37221bd8@posting.google.com>

James Kanze wrote:
 > I would like to know the logic behind the interface of locale.  In
 > particular, I am wondering about the template constructor:
 >
 >     template< typename Facet > locale( locale const&, Facet* ) ;
 >
 > Why not Facet const* for the second paragraph?
...

The Facet template parameter matches a const T, so the cast in
the example you give above is (or should be) unnecessary. There
are implementations out there that fail to accept a const T* as
the second argument to the template ctor, but those are, IMHO,
buggy. Our latest implementation, and recent versions of GNU
libstdc++ accept a const T* in this context.

Regards
Martin


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 2 May 2003 15:18:48 +0000 (UTC)
Raw View
sebor@roguewave.com (Martin Sebor) wrote in message
news:<3EB01287.6020803@roguewave.com>...
> This was never posted (not delivered?)

> James Kanze wrote:
>  > I would like to know the logic behind the interface of locale.  In
>  > particular, I am wondering about the template constructor:

>  >     template< typename Facet > locale( locale const&, Facet* ) ;

>  > Why not Facet const* for the second paragraph?
> ...

> The Facet template parameter matches a const T, so the cast in the
> example you give above is (or should be) unnecessary.

That's what I would have intuitively expected.  From experience,
however, my intuition in such things is often wrong, at least according
to the compilers I use.  Is it also true that I don't need a const
version of:

    template< typename T, size_t N >
    T*
    end( T (&array)[ N ] )
    {
        return array + N ;
    }

?  All of the compilers I've used to date require it (but I've never
understood why).

> There are implementations out there that fail to accept a const T* as
> the second argument to the template ctor, but those are, IMHO,
> buggy. Our latest implementation, and recent versions of GNU libstdc++
> accept a const T* in this context.

Strange.  I discovered the problem as the result of a compiler error.
>From g++ 3.2.2.

You seem to talk as if it were a library issue.  The signatures are
imposed by the standard, and should be the same in any library, no?  And
the compiler error was along the lines of not being able to find a match
for the function, not from anything within the function.

I'll admit that I'm still a bit up in the air about this.  There is no
way for a user to obtain a non-const pointer or reference to a facet
from a locale.  None of the derived interfaces of locale::facet have any
non-const functions.  I presume that the lack of const is due to the
implicit reference counting in facet (   22.1.1.1.2/3).  If this is really
the case, of course, the reference counting won't work if Facet resolves
to a const type, unless the implementation uses a const_cast or a
mutable member in locale::facet.  If the implementation uses const_cast
or a mutable member, there is no reason why the template should not take
a Facet const*.  If it doesn't, then the implementation won't work with
a const pointer anyway, so there is no reason why the template should
take a non const pointer either.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]