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


Groups > comp.lang.c++ > #10790

Re: Setting C++ locale for 1 category

From Nobody <nobody@nowhere.com>
Subject Re: Setting C++ locale for 1 category
Date 2011-10-11 09:08 +0100
Message-Id <pan.2011.10.11.08.08.42.66000@nowhere.com>
Newsgroups comp.lang.c++
References <8d360081-f1ee-4324-a958-df3eb2981340@5g2000yqo.googlegroups.com> <pan.2011.10.10.16.54.25.297000@nowhere.com> <97d603a3-f1ae-4c08-bedb-b20307f57074@h10g2000yqd.googlegroups.com>
Organization Zen Internet

Show all headers | View raw


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.

Back to comp.lang.c++ | Previous | Next — Previous in thread | Find similar | Unroll thread


Thread

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

csiph-web