如何“添加”用户定义的格式标志到basic_ostream?

时间:2017-07-10 09:30:32

标签: c++

我想提供一个流操作符来输出std::chrono::time_point作为GMT日期,我目前有以下内容(仅针对ostream简化):

using datetime_t = std::chrono::system_clock::time_point;

std::ostream& operator<<(std::ostream &out, datetime_t dt) {
    auto time = datetime_t::clock::to_time_t(dt);
    auto under_sec = 
        std::chrono::duration_cast<std::chrono::milliseconds>(
            dt.time_since_epoch() % std::chrono::seconds{1});
    return out << std::put_time(std::gmtime(&time), "%Y-%m-%dT:%H:%M:%S")
               << "." << std::setfill('0') << std::setw(3) << under_sec.count();
}

用法:

auto time = datetime_t::clock::now();
std::cout << time;

这样可行,但它会强制用户:

  • 使用硬编码格式;
  • 输出毫秒。

我想提供自定义流操纵器,允许用户修改这两者,例如:对于第二个(假设包含操纵器的名称空间nm):

std::cout << nm::us << time;

......打印时间可达微秒。

我已经知道如何创建流操作符,例如:

namespace nm {
    std::ios_base& us(std::ios_base &) { /* ... */ }
}

...但我不知道如何“存储”在输出操作符中使用所需的信息。

是否有简单的方法在流中“存储”信息(用户定义的格式标志?)以便在以后的流操作中使用?或者获得稍微相同的行为的另一种方式?

1 个答案:

答案 0 :(得分:2)

正如您在评论中已经发现的那样,是的,溪流有iwordpword存储空间。不是世界上最容易合作的东西(设计好几十年),但是可以使用。

另一种选择是使用已编码的库,例如Howard Hinnant's free, open source, datetime library

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

int
main()
{  
    using namespace date;
    using namespace std::chrono;
    std::cout << format("%FT:%T", floor<microseconds>(system_clock::now())) << '\n';
}

使用此库,可以通过调整输入的精度来控制输出的精度(即使用time_point_castfloor)。

示例输出:

2017-07-10T:11:46:59.354321