簡體   English   中英

std::adjacent_difference 與 std::chrono time_point

[英]std::adjacent_difference with std::chrono time_point

考慮以下代碼:

int main()
{
    std::vector<std::chrono::steady_clock::time_point> time;
    time.push_back(std::chrono::steady_clock::now());
    std::this_thread::sleep_for(std::chrono::milliseconds(4));
    time.push_back(std::chrono::steady_clock::now());
    std::this_thread::sleep_for(std::chrono::milliseconds(7));
    time.push_back(std::chrono::steady_clock::now());
    std::vector<std::chrono::duration<double>> diffs;
    std::adjacent_difference(time.begin(),time.end(),std::back_inserter(diffs));
}

它不編譯(關於不匹配類型的丑陋模板錯誤消息)。 當我嘗試切換到輸入錯誤消息時( std::chrono::time_point<std::chrono::_V2::steady_clock, std::chrono::duration<long, std::ratio<1, 1000000000>>> ) 錯誤消息四處移動。

我的假設是算法不起作用,因為減去 2 個時間點的結果不是時間點,即偽代碼中的這條線是沖突的。

template<class InputIt, class OutputIt>
constexpr // since C++20
OutputIt adjacent_difference(InputIt first, InputIt last, 
                             OutputIt d_first)
{
    if (first == last) return d_first;
 
    typedef typename std::iterator_traits<InputIt>::value_type value_t;
    value_t acc = *first;  
    *d_first = acc; // <-----------------------------------------------------  1
    while (++first != last) {
        value_t val = *first;
        *++d_first = val - std::move(acc); // std::move since C++20  <-------- 2
        acc = std::move(val);
    }
    return ++d_first;
}

所以我有兩個問題:

  1. 我的猜測正確嗎?
  2. 最簡單的解決方法是什么? 我能想到的最好的方法是從時間點到持續時間的丑陋轉變作為中間步驟。

雖然 chrono 是 C++11 我標記這個 C++20 因為我對任何 C++20 解決方案持開放態度,盡管我更喜歡它們不是范圍,因為它們沒有在我的編譯器中實現。

我的假設是算法不起作用,因為減去 2 個時間點的結果不是時間點

實際上,減去兩個time_point不會產生time_point - 它會產生duration <chrono>中, duration s 和time_point s 形成一個仿射空間。 這類似於您不能添加兩個指針,但您可以減去兩個指針 - 您得到的不是指針,而是ptrdiff_t

adjacent_difference算法不支持這樣的仿射類型,因為給定范圍[a, b, c] , output 被指定為[a, ba, cb] 這基本上行不通,因為aba有不同的、不可轉換的類型。

最簡單的方法可能是使用 range-v3:

zip_with(minus(), time, time | drop(1))

產生您實際想要的相鄰差異-不包括第一個值( time_point ),因此您只需獲得一個范圍的duration s。


有一個我總是忘記的transform()的兩個范圍版本(感謝 Conor)。 這也有效:

std::transform(time.begin(), std::prev(time.end()), std::next(time.begin()),
    std::back_inserter(diffs), std::minus());

這基本上是adjacent_difference的“正確”版本的差異。 在 C++20 中,這可以更清楚一點:

std::ranges::transform(time, time | std::views::drop(1),
    std::back_inserter(diffs), std::minus());

您也可以完全濫用adjacent_find

std::adjacent_find(time.begin(), time.end(), [&](auto t1, auto t2){
    diffs.push_back(t2 - t1);
    return false;
});

取自CppReference

計算范圍[first, last)的每個相鄰元素對的第二個和第一個之間的差異,並將它們寫入從d_first + 1開始的范圍。 *first的未修改副本被寫入*d_first

最后一句話是什么讓你絆倒。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM