Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #10774 > unrolled thread

Setting C++ locale for 1 category

Started byStephen Howe <stephen.howe@kantarmedia.com>
First post2011-10-10 08:29 -0700
Last post2011-10-11 09:08 +0100
Articles 4 — 2 participants

Back to article view | Back to comp.lang.c++


Contents

  Setting C++ locale for 1 category Stephen Howe <stephen.howe@kantarmedia.com> - 2011-10-10 08:29 -0700
    Re: Setting C++ locale for 1 category Nobody <nobody@nowhere.com> - 2011-10-10 17:54 +0100
      Re: Setting C++ locale for 1 category Stephen Howe <stephen.howe@kantarmedia.com> - 2011-10-10 14:38 -0700
        Re: Setting C++ locale for 1 category Nobody <nobody@nowhere.com> - 2011-10-11 09:08 +0100

#10774 — Setting C++ locale for 1 category

FromStephen Howe <stephen.howe@kantarmedia.com>
Date2011-10-10 08:29 -0700
SubjectSetting C++ locale for 1 category
Message-ID<8d360081-f1ee-4324-a958-df3eb2981340@5g2000yqo.googlegroups.com>
Hi

I believe that if I do

std::locale::global(std::locale("C"));

that now only does change the global C++ locale but it also passes
through to the C locale as if I had done

setlocale(LC_ALL, "C");

But in C I can do

setlocale(LC_CTYPE, ".1252");

Now exactly how is done in C++?
One of C++'s locale constructors is

locale(const locale& other, const char *name, category cat);

but I am not interested in other, I am interested in name and
category.
How do I set the global locale but just for LC_CTYPE alone?

Thanks

Stephen howe

[toc] | [next] | [standalone]


#10776

FromNobody <nobody@nowhere.com>
Date2011-10-10 17:54 +0100
Message-ID<pan.2011.10.10.16.54.25.297000@nowhere.com>
In reply to#10774
On Mon, 10 Oct 2011 08:29:49 -0700, Stephen Howe wrote:

> How do I set the global locale but just for LC_CTYPE alone?

std::locale::global(std::locale(std::locale(), "C", std::locale::ctype));

This sets the C++ global locale, but I don't know if it's guaranteed to
set the C locale. It works with g++ on Linux, where std::locale().name()
returns a string of the form "LC_CTYPE=C;LC_NUMERIC=en_GB;...".

It's probably safe to assume that it won't work if you construct a locale
by mixing and matching facets rather than categories.

[toc] | [prev] | [next] | [standalone]


#10786

FromStephen Howe <stephen.howe@kantarmedia.com>
Date2011-10-10 14:38 -0700
Message-ID<97d603a3-f1ae-4c08-bedb-b20307f57074@h10g2000yqd.googlegroups.com>
In reply to#10776
On Oct 10, 5:54 pm, Nobody <nob...@nowhere.com> wrote:
> On Mon, 10 Oct 2011 08:29:49 -0700, Stephen Howe wrote:
> > How do I set the global locale but just for LC_CTYPE alone?


> std::locale::global(std::locale(std::locale(), "C", std::locale::ctype));
>
> This sets the C++ global locale, but I don't know if it's guaranteed to
> set the C locale.

I have since learnt:
It is if a name is present ("C").
If a name is given it then does

setlocale(LC_ALL, loc.name.c_str());

So that means the standard is causing an all-category set.
This looks like a flaw in the C++ standard.

Stephen Howe

[toc] | [prev] | [next] | [standalone]


#10790

FromNobody <nobody@nowhere.com>
Date2011-10-11 09:08 +0100
Message-ID<pan.2011.10.11.08.08.42.66000@nowhere.com>
In reply to#10786
On Mon, 10 Oct 2011 14:38:13 -0700, Stephen Howe wrote:

>> > How do I set the global locale but just for LC_CTYPE alone?
> 
>> std::locale::global(std::locale(std::locale(), "C", std::locale::ctype));
>>
>> This sets the C++ global locale, but I don't know if it's guaranteed to
>> set the C locale.
> 
> I have since learnt:
> It is if a name is present ("C").
> If a name is given it then does
> 
> setlocale(LC_ALL, loc.name.c_str());
> 
> So that means the standard is causing an all-category set.

Correct.

> This looks like a flaw in the C++ standard.

It isn't. Well, "flaw" is a bit ambiguous, but the problem which I think
that you're implying doesn't exist.

If the current locale happens to be the C locale, then the result of:

	std::locale(std::locale(), "C", std::locale::ctype)

will actually be the C locale, as you're taking the LC_CTYPE category from
the C locale and the other categories from the C locale also. The
implementation recognises this and gives the resulting locale the name
"C". So there's no error in the resulting locale having the name "C", nor
in std::locale::global calling setlocale(LC_ALL, "C").

Even if you construct a "heterogeneous" locale by combining categories
from different locales, there's no problem with std::locale::global
calling setlocale(LC_ALL, ...), provided that the complete locale can be
described by a string which is acceptable to setlocale().

Bear in mind that the C standard says:

       7.11.1.1  The setlocale function

       Synopsis

       [#1]

               #include <locale.h>
               char *setlocale(int category, const char *locale);

       Description

	...

       [#7] A null pointer for locale causes the setlocale function
       to return a  pointer  to  the  string  associated  with  the
       category  for  the  program's  current locale; the program's
       locale is not changed.175)

       [#8]  The  pointer  to  string  returned  by  the  setlocale
       function  is  such  that  a subsequent call with that string
       value and its associated category will restore that part  of
       the  program's  locale.   The string pointed to shall not be
       modified by  the  program,  but  may  be  overwritten  by  a
       subsequent call to the setlocale function.

	...

       175The implementation shall arrange to encode  in  a  string
          the various categories due to a heterogeneous locale when
          category has the value LC_ALL.

So, if you create a heterogeneous locale by way of multiple setlocale()
calls with different categories, setlocale(LC_ALL, NULL) must return a
string such that setlocale(LC_ALL, str) will restore that locale.

It only becomes tricky if you want to mix your own setlocale() calls with
calls to std::locale::global(). The latter calls the former (where
possible), but the former doesn't touch the C++ global locale. The
construction which I gave earlier changes a single category of the C++
locale, then updates the C locale to match it.

Provided that the C and C++ locales were previously "in sync", the effect
is "as if" setlocale() had been called for a single category; it updates
all categories, but only one of them actually differs from its previous
setting. If the C and C++ locales were out of sync, the call will
resynchronise them. You might consider that a flaw; I consider it a case
of "don't do that".

I think (but don't know for certain) that it should suffice to use:

	std::locale::global(std::locale(setlocale(LC_ALL, NULL)));

to synchronise the C++ locale to the C locale, in the event that the two
have become desynchronised by explicit setlocale() calls.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web