locale and static

Discussion in 'C++' started by daniele, Feb 18, 2010.

  1. daniele

    daniele Guest

    Why the following code doesn't work? It prints the date using the
    default locale instead of mine.
    (compiled with Visual C++ 2008)

    Thanks.
    Daniele


    #include <iostream>
    #include <sstream>
    #include <boost/date_time/posix_time/posix_time.hpp>

    using namespace boost::posix_time;

    class Log
    {
    public:
    Log();
    void Get();
    private:
    static time_facet* myFacet;
    static std::locale myLocale;
    std::eek:stringstream os;
    };


    time_facet* Log::myFacet( new time_facet( "%Y.%m.%d" ) );

    std::locale Log::myLocale( std::locale(), myFacet );

    Log::Log()
    {
    #if 0 // this works
    time_facet* myfacet( new time_facet( "%Y.%m.%d" ) );
    std::locale myLoc( std::locale(), myfacet );
    os.imbue( myLoc );
    #else // this doesn't work!!!
    os.imbue( myLocale );
    #endif
    }

    void Log::Get()
    {
    ptime t( second_clock::local_time() );
    os << t << std::endl;
    fprintf( stderr, "%s", os.str().c_str() );
    fflush( stderr );
    }

    int main( int argc, char* argv[] )
    {
    Log l;
    l.Get();

    return 0;
    }
     
    daniele, Feb 18, 2010
    #1
    1. Advertising

  2. daniele <> writes:

    > Why the following code doesn't work? It prints the date using the
    > default locale instead of mine.
    > (compiled with Visual C++ 2008)
    >
    > Thanks.
    > Daniele
    >
    >
    > #include <iostream>
    > #include <sstream>
    > #include <boost/date_time/posix_time/posix_time.hpp>
    >
    > using namespace boost::posix_time;
    >
    > class Log
    > {
    > public:
    > Log();
    > void Get();
    > private:
    > static time_facet* myFacet;
    > static std::locale myLocale;
    > std::eek:stringstream os;
    > };
    >
    >
    > time_facet* Log::myFacet( new time_facet( "%Y.%m.%d" ) );
    >
    > std::locale Log::myLocale( std::locale(), myFacet );
    >
    > Log::Log()
    > {
    > #if 0 // this works
    > time_facet* myfacet( new time_facet( "%Y.%m.%d" ) );
    > std::locale myLoc( std::locale(), myfacet );
    > os.imbue( myLoc );
    > #else // this doesn't work!!!
    > os.imbue( myLocale );
    > #endif
    > }
    >
    > void Log::Get()
    > {
    > ptime t( second_clock::local_time() );
    > os << t << std::endl;
    > fprintf( stderr, "%s", os.str().c_str() );
    > fflush( stderr );
    > }
    >
    > int main( int argc, char* argv[] )
    > {
    > Log l;
    > l.Get();
    >
    > return 0;
    > }


    Hi Daniele

    Well, I can confirm that I get the same results as you have building
    your code with Microsoft Visual C++ 2008 Express. I had wanted to think
    that it might be something to do with loose guarantees on the
    order/timing of static initialization, but that really shouldn't be a
    problem here as everything is contained by the single translation unit.

    Bumping your code over to gcc-4.4.1 (built with and for the Cygwin 1.7
    environment) I don't see the same problems, and your code is well
    behaved there. So my only thoughts now is that it's either a problem
    with VC, or at a long shot there is some element of undefined or
    implementation-defined behaviour in your example, but I really don't
    think so. I'm not near a copy of the standard to check it out, but if
    my memory serves me well I think that in your example you can expect
    that Log::myFacet is initialized before Log::myLocale, and both before
    the startup of your main code. My sense, then, is that this should work
    as you expect it to.

    Regards

    Paul Bibbings
     
    Paul Bibbings, Feb 19, 2010
    #2
    1. Advertising

  3. daniele

    Robert Fendt Guest

    And thus spake Paul Bibbings <>
    Fri, 19 Feb 2010 05:20:40 +0000:

    > Well, I can confirm that I get the same results as you have building
    > your code with Microsoft Visual C++ 2008 Express. I had wanted to think
    > that it might be something to do with loose guarantees on the
    > order/timing of static initialization, but that really shouldn't be a
    > problem here as everything is contained by the single translation unit.
    >
    > Bumping your code over to gcc-4.4.1 (built with and for the Cygwin 1.7
    > environment) I don't see the same problems, and your code is well
    > behaved there. So my only thoughts now is that it's either a problem
    > with VC, or at a long shot there is some element of undefined or
    > implementation-defined behaviour in your example, but I really don't
    > think so. I'm not near a copy of the standard to check it out, but if
    > my memory serves me well I think that in your example you can expect
    > that Log::myFacet is initialized before Log::myLocale, and both before
    > the startup of your main code. My sense, then, is that this should work
    > as you expect it to.


    I think the difference is most probably the implementation of
    std::locale() in VC++, without having a studio available to
    check before Monday. Could be that it is inlined during
    compilation and MyLocale gets static initialisation, in which
    case it would be initialised with myFacet being still 0. I am a
    bit fuzzy on the details of static initialisation order, but I
    would be surprised if the problem were not somewhere in that
    area.

    IMHO this would still be a standard violation (since myFacet is
    defined before myLocale and clearly gets dynamic initialisation,
    this _should_ mean that myLocale is dynamically initialised as
    well), but a very subtle one.

    Better use a factory function instead of the naked static object
    (i.e., the "construct on first use idiom"), that way you should
    be able to avoid any problems. See also

    http://www.parashift.com/c -faq-lite/ctors.html#faq-10.13

    Regards,
    Robert
     
    Robert Fendt, Feb 19, 2010
    #3
  4. daniele

    daniele Guest

    I tried the "construct on first use idiom" and it works as expected.
    I think you're right: it's a VC++ standard violation.

    Thank you
    Daniele
     
    daniele, Feb 21, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Maurice Hulsman
    Replies:
    1
    Views:
    1,910
    Guus Bosman
    Jul 25, 2004
  2. Replies:
    4
    Views:
    1,046
  3. Gabriel Genellina
    Replies:
    0
    Views:
    736
    Gabriel Genellina
    Feb 18, 2009
  4. zade
    Replies:
    1
    Views:
    641
    James Kanze
    Mar 5, 2010
  5. Sibylle Koczian
    Replies:
    2
    Views:
    1,154
    Sibylle Koczian
    Nov 20, 2010
Loading...

Share This Page