以chrono获取时间类型的名称
Get the name of a time type in chrono
假设我有一个时间测量类,可以通过像这样的持续时间类型进行参数化
template<typename TimeT = std::chrono::milliseconds>
struct measure
{ /* implementation */ };
我想要的是能够打印出TimeT
。我倾向于实现这样的静态成员函数:
static string TimeType() const;
我的问题是:
- 我应该增加一名成员吗?这不应该是静态的吗
- 应该如何实现这一点我应该使用依赖于实现的、非编译时的
typeinfo / name
组合(在这种情况下,我必须删除上面的constexpr
),还是应该选择创建几个专门化,以便每个时间类型返回正确的字符串 - 有没有更标准/更惯用的方法来获取时间类型的名称
欢迎您使用我的<chrono_io>
库。它由一个标题"chrono_io.h"
组成,该标题在文档中链接到。示例用途为:
#include "chrono_io.h"
#include <iostream>
template<typename TimeT = std::chrono::milliseconds>
struct measure
{
TimeT value;
friend
std::ostream&
operator<< (std::ostream& os, const measure& m)
{
using namespace date;
return os << m.value;
}
};
int
main()
{
using namespace std::chrono;
measure<> m1 = {30ms};
std::cout << m1 << 'n';
measure<duration<int, std::ratio<1, 60>>> m2 = {duration<int, std::ratio<1, 60>>{45}};
std::cout << m2 << 'n';
}
输出:
30ms
45[1/60]s
实现这一点的一种方法是对时间类型进行专门化;这样typeid.name()
的不可移植性就不再是一个因素:
/// get the name of the chrono time type
template<typename T> string time_type() { return "unknown"; }
template<> string time_type<std::chrono::nanoseconds >() { return "nanoseconds"; }
template<> string time_type<std::chrono::microseconds>() { return "microseconds"; }
template<> string time_type<std::chrono::milliseconds>() { return "milliseconds"; }
template<> string time_type<std::chrono::seconds >() { return "seconds"; }
template<> string time_type<std::chrono::minutes >() { return "minutes"; }
template<> string time_type<std::chrono::hours >() { return "hours"; }
这个q没有得到太多关注。我发布了一个答案作为代码质量比较的最小基础
当然,这里的困难情况是,在编译时有这些信息,这将需要编译时字符串n’填充
上述的另一个版本是
template<class> struct time_type { constexpr static char const *name = "unknown"; };
template<> struct time_type<nanoseconds > { constexpr static char const *name = "nanoseconds"; };
template<> struct time_type<microseconds> { constexpr static char const *name = "microseconds"; };
template<> struct time_type<milliseconds> { constexpr static char const *name = "milliseconds"; };
template<> struct time_type<seconds > { constexpr static char const *name = "seconds"; };
template<> struct time_type<minutes > { constexpr static char const *name = "minutes"; };
template<> struct time_type<hours > { constexpr static char const *name = "hours"; };
duration
和time_point
都有一个类型为ratio
的period
成员,该成员表示该类型的每个刻度的秒数。
我不相信C++标准提供了一种将10
的特殊幂转换为度量前缀的方法;为此,您必须推出自己的功能。但要注意,这个时期不一定是任何标准的时期;用户可以根据他们喜欢的任何周期(例如年)甚至标准周期创建时间测量,但使用不同的表示类型(例如double
),所以你可能不应该假设。为什么不让它成为另一个参数呢?
您试图做的是反射定义的一部分,更具体地说是运行时类型信息(RTTI),它使代码能够在运行时自行检查。不久前,当我试图制作一个系统,将传入类型的所有成员变量串行化为{ "varName"=<varValue> }
等格式时,我对此进行了深入研究
不幸的是,简单的答案是C++本身并不支持反射,在它提供"类似"功能(即<type_traits>
和typeid()
)的地方,还有很多不足之处。最好的结果将来自生成您需要的数据的自定义构建步骤,我决定反对这种方法,所以在这种情况下,不能真正帮助"如何",但这些方法显然在可移植性方面受到限制。
然而,您已经提到的模板专业化方法是我所见过的C++运行时反射的最佳实现的一步,它使用宏的组合来生成类描述符。
MFC宏DECLARE_DDYNAMIC和IMPLEMENT_DYNAMIC是为类创建其中一个描述符所需的所有污染,然后添加函数IsKindOf()
、GetRuntimeClass()
等,最有用的通常是返回CRuntimeClass
的GetRuntimeClass()
。
为了实现类似的东西,你可以使用类似的东西;
#define MakeClassDescriptor(classname)
private:
class classname ## Descriptor
{
public:
static const char* GetName() { return #classname; }
};
public:
typedef classname ## Descriptor ClassDescriptor;
class Test
{
public:
Test() {};
MakeClassDescriptor(Test);
};
这将允许您通过Test::ClassDescriptor::GetName()
访问该名称
当然,还有其他方法和您自己的规范规定了如何实现这一点,例如,类从模板化RTTI类继承的方法,请参阅Dominic Filion在《游戏编程宝石5 》一书中撰写的文章"在C++中使用反射模板"
- 使用简单类型列表实现的指数编译时间.为什么
- 时间复杂度 当具有复合数据类型(如元组或对)时?
- 标准::时间::d类型的挥发性对象
- 指向(数据)成员的指针作为非类型模板参数,例如具有自动存储持续时间/无链接
- 将结构时间规范添加到类(似乎没有其他类型的)会导致EXEC_BAD_ACCESS
- 无法将 int 类型转换为时间类型(我的类类型)
- C++编译时间类型确定
- 通过引用传递基元类型(如 int、bool)是否比按值传递有任何加速?还是会恶化时间/空间的使用
- C 函数在编译时间返回类型
- 访问和存储/解析性std :: Chrono ::持续时间:: milliseconds(cpprest)时使用什么类型
- 如何恢复注册表项的所有元素?(上次写入时间,类型,值,名称...这是正确的方法吗?
- C++ - 函数中的局部指针变量具有什么类型的存储持续时间以及它们存储在哪里?
- 如何使用谷歌测试打印标准::时间类型
- 在编译时间之前抓取常数值
- C 编译时间检查模板类型中是否存在方法
- 在编译时间检查模板参数类型是否设置或多键,并且容器的元素类型是算术的
- 运算符/ STD :: Chrono ::持续时间和自定义类型与Clang
- 编译时间矩阵模板类型
- 捕获类型调度时间
- 通过C++模板编译从整数到类型的时间查找