c++ - 通用类标准时间独立模板秒表
问题描述
我有一个简单的秒表类,它基本上std::chrono::steady_clock::now() - this->start_
在其实现中用于测量经过的时间。我决定升级它并使其完全通用,符合标准,不依赖于特定的时钟类型,因此用户可以指定自己的时钟类型。为了方便起见,我还有一个模板stopwatch::operator DurationType() const
,可以转换为特定的持续时间类型,例如:
std::chrono::milliseconds msecs = stopwatch;
但是有一个问题:我无法摆脱一个chrono
标题,因为我正在使用它的duration_cast
.
我想出了2个想法。其中一个可以工作,但不是很方便,另一个根本不工作,而且很丑。
// stopwatch.h
#pragma once
// #include <chrono>
namespace eld
{
template <typename ClockType,
typename DurationCaster>
class stopwatch
{
public:
using clock_type = ClockType;
using duration = typename clock_type::duration;
stopwatch()
: start_(clock_type::now())
{}
void reset()
{
start_ = clock_type::now();
}
typename clock_type::duration result() const
{
return clock_type::now() - start_;
}
template<typename Duration>
Duration result() const
{
// return std::chrono::duration_cast<Duration>(result()); // TODO: remove this
return DurationCaster()(Duration(), result());
}
template<typename Duration>
operator Duration() const
{
return result<Duration>();
}
// This is ugly and does not work
// template <typename Caster>
// auto operator()(Caster caster) -> decltype(Caster::operator()(typename clock_type::time_point))
// {
// return caster(result());
// }
private:
typename clock_type::time_point start_;
};
}
// dummy.cpp
#include <stopwatch/stopwatch.h>
#include <iostream>
#include <chrono>
#include <thread>
// this is inconvenient
struct DurationCaster
{
template<typename ToDuration, typename FromDuration>
constexpr ToDuration operator()(ToDuration, FromDuration fromDuration) const
{
return std::chrono::duration_cast<ToDuration>(fromDuration);
}
};
int main()
{
eld::stopwatch<std::chrono::steady_clock, DurationCaster> steadyWatch{};
std::this_thread::sleep_for(std::chrono::milliseconds(20));
std::chrono::nanoseconds nanoseconds = steadyWatch.result();
std::cout << nanoseconds.count() << std::endl;
std::chrono::milliseconds milliseconds = steadyWatch;
std::cout << milliseconds.count() << std::endl;
// This is ugly and does not work
// milliseconds = steadyWatch([](typename decltype(steadyWatch)::duration from)
// {
// return std::chrono::duration_cast<std::chrono::milliseconds>(from);
// });
return 0;
}
std::chrono::duration_cast
尽管第一个选项虽然不便,但仍然有效,但我想知道是否可以以更优雅的方式摆脱标题。或者这是最好的吗?
PS:我的第二种方法有什么问题?为什么我编译不出来?
解决方案
如果您想使用第一种方法,也许将 DurationCaster 作为参数传递给构造函数,那么可以使用函数而不仅仅是函数对象?而且你不需要DurationCaster
每次都创建operator()
,只做一次。
或者,您可以使用 default DurationCaster
,它duration_cast
在引擎盖下使用,定义如下typename DurationCaster = your_default_caster
关于为什么不工作的第二个:正如我所见,这里有一个错误decltype(Caster::operator()(typename clock_type::time_point))
,您将其operator
称为静态成员函数,这是错误的。
这应该有效:
template <typename Caster>
auto operator()(Caster caster) -> typename std::result_of<Caster(typename clock_type::duration)>::type
{
return caster(result());
}
PS:我知道result_of
已弃用,但问题是关于 cpp11
推荐阅读
- postgresql - 使用 PostgreSQL 函数中的字符串生成唯一的字符串 ID
- glsl - WebGL 中的体积渲染
- c# - 使用 System.Drawing.Printing 在 .NET Core 中打印 PDF
- flutter - Flutter 打印特定值
- opencv - openCV 如何使用物点和图像点估计焦距
- sql - 优化查询以获取其他表中不存在的 ID
- javascript - 根据选择选项更改 php 变量值
- sql - 如何在 SQL 中获得不同的路由?
- javascript - TypeError: Select is not a constructor when using Svelte and jest
- javascript - 承诺的 Vuex 模态?