C++ C++;11本地时间的替代方案\u r

C++ C++;11本地时间的替代方案\u r,c++,time,c++11,strftime,C++,Time,C++11,Strftime,C++根据strftime定义时间格式化函数,这需要struct tm的“分解时间”记录。然而,C和C++03语言没有提供线程安全的方法来获取这样的记录;整个程序只有一个masterstruct tm 在C++03中,这或多或少还行,因为该语言不支持多线程;它只支持支持多线程的平台,然后提供POSIX等工具 C++11还定义了新的时间实用程序,它与未分解的time\t类型接口,该类型将用于重新初始化全局struct tm。但是获得时间不是问题 我是否遗漏了什么,或者这个任务仍然需要依赖POSIX

C++根据
strftime
定义时间格式化函数,这需要
struct tm
的“分解时间”记录。然而,C和C++03语言没有提供线程安全的方法来获取这样的记录;整个程序只有一个master
struct tm

在C++03中,这或多或少还行,因为该语言不支持多线程;它只支持支持多线程的平台,然后提供POSIX等工具

C++11还定义了新的时间实用程序,它与未分解的
time\t
类型接口,该类型将用于重新初始化全局
struct tm
。但是获得时间不是问题

我是否遗漏了什么,或者这个任务仍然需要依赖POSIX

编辑:以下是一些解决方案代码。它与提供
::localtime\r
的多线程环境和仅提供
std::localtime
的单线程环境保持兼容性。它也可以很容易地用于检查其他功能,例如
posix::localtime\u r
::localtime\u s
或您拥有的其他功能

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 ); }
名称空间查询{
字符localtime_r(…);
结构具有\u localtime\r
{enum{value=sizeof localtime_r(std::declval(),std::declval())
==sizeof(std::tm*)};};
模板struct safest\u localtime{
静态std::tm*调用(std::time\u t const*t,std::tm*r)
{返回localtime_r(t,r);}
};
模板结构最安全\u localtime{
静态std::tm*调用(std::time\u t const*t,std::tm*r)
{return std::localtime(t);}
};
}
std::tm*localtime(std::time\u t const*t,std::tm*r)
{return query::safest_localtime()。调用(t,r);}

您没有遗漏任何内容

下一个C标准(可能在今年发布)在附录K中有定义:

struct tm *localtime_s(const time_t * restrict timer,
                       struct tm * restrict result);
这个新函数是线程安全的!但不要太高兴。有两个主要问题:

  • localtime\u s
    是对C11的可选扩展

  • C++11引用C99,而不是C11<代码>本地时间在C++11中找不到,可选或不可选

  • 更新

    在回答这个问题的4年里,我对C++工具在这方面的设计也很差。我被激励创建现代C++工具来处理这个问题:

    #包括“tz.h”
    #包括
    int
    main()
    {
    使用名称空间日期;
    自动本地时间=进行分区(当前分区(),标准::时钟::系统时钟::现在();
    
    std::难道你不能将
    localtime
    封装在一个使用互斥锁的函数中吗?或者其他更轻的锁形式?我不知道这里怎么需要POSIX。@Nicol:是的,但只有当没有其他人尝试做同样的事情时,这才是安全的。换句话说,它在程序中工作,而不是在库中。但是他们会调用非线程-从线程代码中获得安全函数,这样他们就可以得到应得的。你可以公开一个函数供他们使用,如果他们使用标准的C one,那么他们就会得到未定义的行为。@Nicol:什么?我正在编写一个不能向其用户提供此类限制的库。@Nicol:我的库不是多线程的,但我希望它是多线程的与多线程代码兼容。您建议使用互斥体保护并调用
    localtime
    正是您建议我告诉用户不要这样做的。我不能坚持我的互斥体是
    localtime
    的互斥体-库的功能是无关的。无论如何,任何与互斥体相关的解决方案都是错误的,因为我的代码根本不是多线程的,它只是线程安全的…而且他们更改了名称!谢谢你提供的信息。不管怎样,可以查询
    localtime\r
    是否可用,或者求助于
    localtime
    。所以看起来我也可以吃蛋糕了。
    #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';
    }