C ++ 11替代localtime_r [英] C++11 alternative to localtime_r

查看:154
本文介绍了C ++ 11替代localtime_r的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在C ++ 03中,不太好,因为语言不支持多线程;它只支持支持多线程的平台,然后提供像POSIX这样的工具 localtime_r



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



我缺少一些东西或者这个任务仍然需要依靠POSIX?



EDIT:这是一些解决方法代码。它保持与提供 :: localtime_r 的多线程环境和只提供 std :: localtime 的单线程环境的兼容性。它可以很容易地适用于检查其他函数,如 posix :: localtime_r :: localtime_s

 命名空间查询{
char localtime_r(...);

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


模板< bool可用> struct safest_localtime {
static std :: tm * call(std :: time_t const * t,std :: tm * r)
{return localtime_r(t,r); }
};

模板<> 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); }


解决方案

>

下一个C标准(可能是今年到期)确实已在附件K中定义:

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

这个新函数是线程安全的!但不要太高兴。有两个主要问题:


  1. localtime_s 对C11的扩展。


  2. C ++ 11引用C99,而不是C11。 local_time_s 在C ++ 11中找不到,是否可选。


更新



在我回答这个问题后的4年里,我也对C ++的糟糕设计感到失望工具在这方面。我有动机创建现代C ++工具来处理这个问题:



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

  #include tz.h
#include< iostream>

int
main()
{
使用命名空间date;
auto local_time = make_zoned(current_zone(),std :: chrono :: system_clock :: now());
std :: cout<< local_time<< '\\\
';
}

这只是输出给我:



2015-10-28 14:17:31.980135 EDT



local_time code> std :: chrono :: system_clock :: time_point 和 time_zone 表示本地时间。



存在用于将 std :: chrono :: system_clock :: time_point 打成人类可读字段类型的实用程序,例如年,月,日,小时,分钟,秒和子秒。以下是关于这些(非时区)作品的演示:



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



这当然是线程安全的是现代C ++)。


C++ defines time formatting functions in terms of strftime, which requires a struct tm "broken-down time" record. However, the C and C++03 languages provide no thread-safe way to obtain such a record; there is just one master struct tm for the whole program.

In C++03, this was more or less OK, because the language didn't support multithreading; it merely supported platforms supporting multithreading, which then provided facilities like POSIX localtime_r.

C++11 also defines new time utilities, which interface with the non-broken-down time_t type, which is what would be used to reinitialize the global struct tm. But obtaining a time_t isn't the problem.

Am I missing something or does this task still require reliance on POSIX?

EDIT: Here is some workaround code. It maintains compatibility with multithreaded environments that provide ::localtime_r and single-threaded environments that provide only std::localtime. It can easily be adapted to check for other functions as well, such as posix::localtime_r or ::localtime_s or 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 ); }

解决方案

You're not missing anything.

The next C standard (due out probably this year) does have defined in Annex K:

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

And this new function is thread safe! But don't get too happy. There's two major problems:

  1. localtime_s is an optional extension to C11.

  2. C++11 references C99, not C11. local_time_s is not to be found in C++11, optional or not.

Update

In the 4 years since I answered this question, I have also been frustrated by the poor design of C++ tools in this area. I was motivated to create modern C++ tools to deal with this:

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';
}

This just output for me:

2015-10-28 14:17:31.980135 EDT

local_time is a pairing of std::chrono::system_clock::time_point and time_zone indicating the local time.

There exists utilities for breaking the std::chrono::system_clock::time_point into human-readable field types, such as year, month, day, hour, minute, second, and subseconds. Here is a presentation focusing on those (non-timezone) pieces:

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

All of this is of course thread safe (it is modern C++).

这篇关于C ++ 11替代localtime_r的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆