【问题标题】:C++: setting time using suffixesC++:使用后缀设置时间
【发布时间】:2019-05-19 20:32:01
【问题描述】:

告诉我,C++ 11/14/17 中是否存在以下内容:

1) 使用时间后缀设置时间

double time1 = 1s; // time1 = 1.0
double time2 = 2m; // time2 = 120.0
double time3 = 7ms; // time3 = 0.007 

2) 获取设置后缀的时间字符串值

std::cout << getTime(time1); // cout 1s
std::cout << getTime(time2); // cout 2s
std::cout << getTime(time3); // cout 7ms

【问题讨论】:

  • 这些是后缀,不是前缀。

标签: c++ c++11 time c++14 user-defined-literals


【解决方案1】:
  1. 是的,从 C++14 开始,您可以使用用户定义的文字 described here 创建持续时间:

    #include <chrono>
    using namespace std::literals;
    auto time1 = 1s; // std::chrono::seconds{1}
    auto time2 = 2min; // std::chrono::minutes{2}
    auto time3 = 7ms; // std::chrono::milliseconds{7}
    

    这些创建存储整数值的类型安全对象。您可以在内部相当轻松地使用 double,但这些特化并没有开箱即用的漂亮类型别名:

    namespace chr = std::chrono;
    using dbl_seconds = chr::duration<double, chr::seconds::period>;
    // Likewise for other units
    dbl_seconds time1 = 1s;
    

    如果您绝对需要内部值(通常是个坏主意),您可以使用.count() 访问它。

  2. 这是计划在 C++20 中出现的:

    std::cout << time1; // 1s, or 1.000000s if using double
    

    在那之前,你可以用标准 C++ 做的最好的事情就是接受它并使用count()

    std::cout << time1.count() << 's'; // 1s
    

要更好地了解图书馆,请观看Howard's CppCon talk。他的其他演讲涵盖了计划中的 C++20 添加。

【讨论】:

    【解决方案2】:

    所有现代 C++ 时间实用程序都在 the reference for &lt;chrono&gt; library

    中进行了描述
    1. 是的,从开始我们有std::literals::chrono_literals, 允许我们使用以下文字:

      operator""h
      operator""min
      operator""s
      operator""ms
      operator""us
      operator""ns
      

      例如(从 cppreference):

      #include <iostream>
      #include <chrono>
      
      int main()
      {
          using namespace std::chrono_literals;
          auto day = 24h;
          auto halfhour = 0.5h;
          std::cout << "one day is " << day.count() << " hours\n"
                    << "half an hour is " << halfhour.count() << " hours\n";
      }
      

    1. 不是直接,而是从开始存在 std::chrono::duration, 有几种方便的辅助类型来帮助正确描述时间 (例如std::chrono::millisceondsstd::chrono::hours 等)。使用 这些,您可以轻松地做需要的事情。

      缩短的示例来自 cppreference。 如您所见,单位必须单独打印,但选择 使用一些模板魔法,打印正确的单元就很容易了。

      #include <iostream>
      #include <chrono>
      
      int main()
      {     
          std::chrono::seconds sec(1);
      
          std::cout << sec.count() <<" second is equal to:\n";
      
          // integer scale conversion with no precision loss: no cast
          std::cout << std::chrono::microseconds(sec).count() << " microseconds\n";
      
          // integer scale conversion with precision loss: requires a cast
          std::cout << std::chrono::duration_cast<std::chrono::minutes>(sec).count()
                    << " minutes\n";
      }
      

    【讨论】:

      【解决方案3】:
      1. ,通过std::chrono_literals

      2. 不是直接,但您可以打印typeid(可用于调试)或自己为流式传输持续时间提供重载。

      我在这里包含了operator&lt;&lt; 的显式重载,但作为@JeJo,它也可以使用模板来完成:https://wandbox.org/permlink/o495eXlv4rQ3z6yP

      #include <iostream>
      #include <chrono>
      #include <typeinfo>
      
      using namespace std::chrono_literals;
      
      // example overloads for streaming out durations
      std::ostream& operator<<(std::ostream& os, const std::chrono::nanoseconds& v) {
          return os << v.count() << "ns";
      }
      std::ostream& operator<<(std::ostream& os, const std::chrono::microseconds& v) {
          return os << v.count() << "us";
      }
      std::ostream& operator<<(std::ostream& os, const std::chrono::milliseconds& v) {
          return os << v.count() << "ms";
      }
      std::ostream& operator<<(std::ostream& os, const std::chrono::seconds& v) {
          return os << v.count() << "s";
      }
      std::ostream& operator<<(std::ostream& os, const std::chrono::minutes& v) {
          return os << v.count() << "min";
      }
      std::ostream& operator<<(std::ostream& os, const std::chrono::hours& v) {
          return os << v.count() << "h";
      }
      
      int main() {
          auto time1 = 1s;
          auto time2 = 2min;
          auto time3 = 7ms;
          std::cout << time1.count() << " " << typeid(time1).name() << "\n";
          std::cout << time2.count() << " " << typeid(time2).name() << "\n";
          std::cout << time3.count() << " " << typeid(time3).name() << "\n";
          std::cout << time1 << "\n";
          std::cout << time2 << "\n";
          std::cout << time3 << "\n";
      }
      

      可能的输出:

      1 NSt6chrono8durationIlSt5ratioILl1ELl1EEEE
      2 NSt6chrono8durationIlSt5ratioILl60ELl1EEEE
      7 NSt6chrono8durationIlSt5ratioILl1ELl1000EEEE
      1s
      2min
      7ms
      

      【讨论】:

        【解决方案4】:

        1) 没有

        2) 不,不直接。存在转换为 chrono 类型的运算符(尽管这是整数而不是双精度数),但它们没有 operator&lt;&lt; 重载。 boost::chrono 有漂亮的打印机(尽管它们已被弃用)。但是,它们是完整的,而不仅仅是简短的形式。

        见:

        【讨论】:

        • 嗯,显然第一个问题的答案是“是”。我建议你删除这个答案,否则你很快就会被否决。
        • 不,文字创建了计时类型(如 2 中所述)。 OP 示例创建双打。
        • ...然后重写你的一个字答案来解释你的意思。
        猜你喜欢
        • 1970-01-01
        • 2010-11-28
        • 1970-01-01
        • 2019-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-13
        相关资源
        最近更新 更多