考虑以下代码:
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进行了标记,尽管我更希望它们不属于range,因为它们未在编译器中实现。
我的假设是该算法不起作用,因为减去2个时间点的结果不是一个时间点
确实,减去两个time_point
s不会产生a-time_point
它会产生a duration
。在<chrono>
,duration
和中time_point
形成仿射空间。这类似于无法添加两个指针的方式,但是可以减去两个指针-得到的不是指针,而是一个ptrdiff_t
。
该adjacent_difference
算法不支持此类仿射类型,因为给定范围[a, b, c]
指定输出为[a, b-a, c-b]
。这基本上是行不通的,因为a
并且b-a
具有不同的,不可转换的类型。
最简单的方法可能是使用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;
});
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句