【问题标题】:How to declare a std::chrono::duration<double> variable in c++如何在 C++ 中声明 std::chrono::duration<double> 变量
【发布时间】:2019-05-23 12:36:40
【问题描述】:

我正在编写一个代码,我正在计算持续时间,然后将其保存在列表中。

auto start_time = std::chrono::high_resolution_clock::now();
/*
 *some code here
*/
auto finish_time = std::chrono::high_resolution_clock::now();

std::chrono::duration<double> time_duration = finish_time - start_time ;

现在我需要将time_duration 保存在给定索引的列表中。如果该给定索引已经包含一个值,我需要将time_duration 与该索引的当前值相加并保存。为此,我有以下列表和代码:

list <std::chrono::duration<double>> dTimeList;

auto iter = dTimeList.begin();
advance(iter, 0);  
*iter+= time_duration; //Error at this line

但是运行上面的代码我得到以下错误:

这个错误很可能是因为我有一个空列表,其中没有任何项目。这就是为什么我想在第 0 个索引处添加一个项目,如下所示:

auto itr = dTimeList.begin();
advance(itr, 0);
std::chrono::duration<double> t = 0.0;
dTimeList.insert(itr, t);

但上面也给出了下面的错误。我该如何解决这个问题。谢谢

No suitable constructor available to convert double to std::chrono::duration&lt;double&gt;

【问题讨论】:

  • 当迭代器位于end() 时,尝试推进迭代器时遇到的错误,正如您所知道的,很清楚。但是,您永远不会告诉我们第二次尝试出了什么问题。创建minimal reproducible example
  • 使用list.push_back(t)将项目添加到列表中,不要使用advance(itr, 0)
  • @TedLyngmo 我已经编辑了问题。
  • 没有合适的构造函数可用于将double 转换为std::chrono&lt;double&gt;。但是您可以使用显式构造:std::chrono::duration&lt;double&gt; t{0.0};.
  • @SAndrew A list 如果您想要索引,则不适合。 (它们实际上不适用于大多数事情,并且在野外很少观察到。)使用std::vectorstd::deque

标签: c++ list time chrono


【解决方案1】:

您可能不应该使用列表在索引处存储数据。尝试改用std::unordered_map

#include <unordered_map>
auto start_time = std::chrono::high_resolution_clock::now();
/*
 *some code here
*/
auto finish_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> time_duration = finish_time - start_time ;

typedef int YourObjectIdType;

std::unordered_map<YourObjectIdType, std::chrono::duration<double>> dTimes;

现在像这样插入或更新项目:

dTimes[objectId] += time_duration;

或者像这样:

 auto it = dTimes.find(objectId);
 if (it != dTimes.end()) {
      *it += time_duration;
 } else {
      dTimes.insert(std::make_pair(objectId, time_duration));
 }

另外,你可以用同样的方法使用std::map,它会稍微慢一些,但是[begin(), end()) 范围是排序的。

【讨论】:

  • 感谢这个例子。你能告诉我这是什么意思吗typedef int YourObjectIdType;
  • 正如我在您之前的问题中看到的,您有一些(对我而言)未知类型的对象 id,您可以使用该 object_id 作为 std::unordered_mapstd::map 中对应类型的键。 typedef 不是必需的。我只是假设类型是int
  • 您可以使用intstd::size_t 索引作为该映射的键
  • 赞成,但考虑使用dTimes.emplace(objectId, time_duration); 而不是dTimes.insert(std::make_pair(...
  • 我看不到按索引 0,1,2,3 ... N 存储的逻辑,并且不使用向量?我们知道这里的应用程序逻辑是什么吗?可能 std::vector 就足够了。
【解决方案2】:

您正在尝试写入结束迭代器。当列表为空时,dTimeList.begin() == dTimeList.end(),所以你不能写它。

你需要先检查索引是否存在,否则扩展列表:

void add_time_to_list(
    std::list<std::chrono::duration<double>>& l,
    const std::chrono::duration<double>& t,
    std::size_t index = 0
) {
    if (index < l.size()) {
        *std::next(l.begin(), index) += t;
    } else if (index == l.size()) {
        // New element; add to back
        l.push_back(t);
    } else {
        // Here you can throw an error that index is too big
        // or append 0 until it gets to the desired size or something
    }
}

请注意,访问这样的任意索引可能意味着您不想要std::list。使用std::vector*std::next(l.begin(), index) 变为 l[index])会更容易。我还建议std::map,函数可以写成:

void add_time_to_list(
    std::map<std::size_t, std::chrono::duration<double>>& m,
    const std::chrono::duration<double>& t,
    std::size_t index = 0
) {
    m[index] += t;  // if m[index] doesn't exist, it is default constructed. 
}

【讨论】:

    【解决方案3】:

    没有合适的构造函数可用于将 double 转换为 std::chrono::duration

    我敢建议处理 std::list 远不是这里的核心问题。

    std::chrono打交道,应该知道它的基本概念。对于此处未解释的内容,请在 cppreference.com 上查找

    第一步。您决定需要/想要使用哪个时钟。

    using Clock = typename std::chrono::high_resolution_clock ;
    

    第二步。您使用在其中声明的持续时间嵌套类型。在您的用例中,您希望有一个持续时间序列。

    using time_durations_sequence_type = std::vector<Clock::duration> ;
    

    类型命名非常重要。我故意使用通用术语“序列”。您可能会推动 std::list 的想法来实现它,但我不明白为什么。因此我在上面使用std::vector

    另外请注意,我不使用doublelong int 作为“持续时间”类型。首先std::duration 是“事件发生所需的时间”。其次,它不是标量,而是类类型。传统上,从 C 年开始,时间概念仅基于刻度。

    因此,长话短说,我们使用 std::duration 概念,具体化为我们选择在这里使用的“时钟”中的嵌套类型。

       // not a point in time
       Clock::duration
       //
       // there is no guarantee above 
       // is the same type as
       // std::chrono::duration<double>
       // and we do not need one
    

    以上就是我们继续实现您需要的功能所需的全部内容。

         // two points in time
         auto start_time = Clock::now();
         auto finish_time = Clock::now();
    
          // the duration
          Clock::duration time_duration = finish_time - start_time ;
    

    现在我们将持续时间存储在我们的序列类型中。

          time_durations_sequence_type tdst{ time_duration } ;
    

    在其他地方,我们使用我们累积的存储持续时间序列。

    //  time_durations_sequence_type tdst
    for (auto duration : tdst ) {
            std::cout << std::endl 
               << duration.count() << " nano seconds" 
               << std::endl;
    }
    

    请注意上面我们如何使用count() 方法来获取实际的滴答声,在 std::chrono 默认情况下,它确实代表纳秒。

    工作代码是here

    【讨论】:

      猜你喜欢
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 2016-07-20
      • 2012-08-21
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多