38

C ++は、 「分解された時間」レコードstrftimeを必要とするという観点から時間フォーマット関数を定義します。struct tmただし、CおよびC ++ 03言語は、そのようなレコードを取得するためのスレッドセーフな方法を提供していません。struct tmプログラム全体でマスターは1つだけです。

C ++ 03では、言語がマルチスレッドをサポートしていなかったため、これは多かれ少なかれ問題ありませんでした。マルチスレッドをサポートするプラットフォームをサポートするだけで、POSIXなどの機能を提供していlocaltime_rました。

C ++ 11は、グローバルを再初期化するために使用される、ブレークダウンさtime_tていないタイプとインターフェイスする新しい時間ユーティリティも定義します。しかし、を取得することは問題ではありません。struct tmtime_t

私は何かが足りないのですか、それともこのタスクはまだPOSIXに依存する必要がありますか?

編集:ここにいくつかの回避策のコードがあります。::localtime_rを提供するマルチスレッド環境およびのみを提供するシングルスレッド環境との互換性を維持しますstd::localtimeposix::localtime_rまたは、::localtime_sまたはwhat-have-youなどの他の機能もチェックするように簡単に適合させることができます。

namespace query {
    char localtime_r( ... );

    struct has_localtime_r
        { enum { value = sizeof localtime_r( std::declval< std::time_t * >(), std::declval< std::tm * >() )
                        == sizeof( std::tm * ) }; };


    template< bool available > struct safest_localtime {
        static std::tm *call( std::time_t const *t, std::tm *r )
            { return localtime_r( t, r ); }
    };

    template<> struct safest_localtime< false > {
        static std::tm *call( std::time_t const *t, std::tm *r )
            { return std::localtime( t ); }
    };
}
std::tm *localtime( std::time_t const *t, std::tm *r )
    { return query::safest_localtime< query::has_localtime_r::value >().call( t, r ); }
4

1 に答える 1

28

あなたは何も見逃していません。

次のC規格(おそらく今年の予定)は、付録Kで定義されています。

struct tm *localtime_s(const time_t * restrict timer,
                       struct tm * restrict result);

そして、この新しい関数はスレッドセーフです!しかし、あまり幸せにならないでください。2つの大きな問題があります。

  1. localtime_sC11のオプションの拡張機能です。

  2. C ++ 11は、C11ではなくC99を参照します。 local_time_sオプションかどうかにかかわらず、C++11にはありません。

アップデート

この質問に答えてから4年間、この分野でのC++ツールの設計が貧弱であることに不満を感じています。私はこれに対処するための最新のC++ツールを作成するように動機付けられました。

http://howardhinnant.github.io/date/tz.html

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    auto local_time = make_zoned(current_zone(), std::chrono::system_clock::now());
    std::cout << local_time << '\n';
}

これは私のためにちょうど出力します:

2015-10-28 14:17:31.980135 EDT

local_timeとのペアでstd::chrono::system_clock::time_pointありtime_zone、現地時間を示します。

std::chrono::system_clock::time_point年、月、日、時、分、秒、サブ秒など、人間が読める形式のフィールドに分割するためのユーティリティがあります。これらの(タイムゾーン以外の)部分に焦点を当てたプレゼンテーションは次のとおりです。

https://www.youtube.com/watch?v=tzyGjOm8AKo

もちろん、これはすべてスレッドセーフです(最新のC ++です)。

アップデート2

上記は、構文が少し変更されたC++20の一部になりました。

#include <chrono>
#include <iostream>

int
main()
{
    namespace chr = std::chrono;

    chr::zoned_time local_time{chr::current_zone(), chr::system_clock::now()};
    std::cout << local_time << '\n';
}
于 2011-09-06T02:44:14.727 に答える