[英]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;
}
所以我有兩個問題:
雖然 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]
。 這基本上行不通,因為a
和ba
有不同的、不可轉換的類型。
最簡單的方法可能是使用 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.