C++ 在chrono中获取时间类型的名称
假设我有一个时间测量类,可以通过如下的duration类型进行参数化C++ 在chrono中获取时间类型的名称,c++,c++11,c++14,chrono,C++,C++11,C++14,Chrono,假设我有一个时间测量类,可以通过如下的duration类型进行参数化 template<typename TimeT = std::chrono::milliseconds> struct measure { /* implementation */ }; 我的问题是: 我应该添加一个成员吗?这不应该是静态的吗 应该如何实现此主体?我应该使用依赖于实现的非编译时typeinfo/name组合(在这种情况下,我必须删除上面的constepr),还是选择创建几个专门化,以返回每个时间类
template<typename TimeT = std::chrono::milliseconds>
struct measure
{ /* implementation */ };
我的问题是:
typeinfo/name
组合(在这种情况下,我必须删除上面的constepr
),还是选择创建几个专门化,以返回每个时间类型的正确字符串李>
duration
和time\u point
都有一个period
类型的成员ratio
,表示该类型每滴答的秒数
< >我不相信C++标准提供了一种将代码> 10 < /> >的特殊幂转换成度量前缀的方法;为此,您必须推出自己的功能。但是要知道,这个时间段不必是任何一个标准的时间段;用户可以根据自己喜欢的任何时间段(例如年)或甚至标准时间段创建时间度量,但使用不同的表示类型(例如,
double
),因此您可能不应该假设。为什么不让它成为另一个参数?一种方法是专门化时间类型;这样一来,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"; }
///获取计时时间类型的名称
模板字符串time_type(){返回“未知”;}
模板字符串time_type(){返回“纳秒”;}
模板字符串time_type(){返回“微秒”;}
模板字符串time_type(){返回“毫秒”;}
模板字符串time_type(){返回“秒”;}
模板字符串time_type(){返回“分钟”;}
模板字符串time_type(){返回“hours”;}
这个问题没有得到太多的关注。我发布了一个答案作为代码质量比较的最小基数
当然,这里最困难的情况是在编译时获得这些信息,这需要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"; };
template struct time_type{constexpr static char const*name=“unknown”;};
模板结构时间类型{constexpr static char const*name=“纳秒”;};
模板结构时间类型{constexpr static char const*name=“microseconds”;};
模板结构时间\u类型{constexpr static char const*name=“毫秒”;};
模板结构时间类型{constexpr static char const*name=“seconds”;};
模板结构时间类型{constexpr static char const*name=“minutes”;};
模板结构时间类型{constexpr static char const*name=“hours”;};
欢迎您使用我的。它由一个标题组成,“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';
}
您试图做的是定义的一部分,更具体地说,是运行时类型信息(),它使代码能够在运行时进行自我检查。不久前,当我试图创建一个系统,将传入类型的所有成员变量序列化为
{“varName”=}格式时,我仔细研究了这一点
遗憾的是,简单的答案是C++不支持反射,在提供类似功能的地方(即,它)还有很多不足之处。最好的结果将来自生成所需数据的定制构建步骤,我决定反对这种方法,所以在这种情况下,无法真正帮助解决“如何”的问题,但这些方法显然在可移植性方面受到限制
但是,您已经提到的模板特化方法是我看到的C++运行时反射的最佳实现的一个步骤,它使用宏的组合来生成类描述符。p> MFC宏和是为类创建其中一个描述符所需的全部参数,这些描述符随后添加函数
IsKindOf()
,GetRuntimeClass()
,最有用的通常是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++中进行反射”获取“名称”的标准方法类型的,正在使用返回的类。但是,C++中没有任何东西可以说出名称,它可能是编译器的类型名称,或者别的什么。但是我更感兴趣的是为什么你会想要这个?这看起来像。@JoachimPileborg我正在打印一个基准,只想在计时栏中添加一个标题。我相信,由于时间类型是在编译时知道的,所以我不应该在其他地方重复这些信息(并为爬行的bug腾出空间)。基本上我所做的是从更高的层次使用abstraction@JoachimPileborg如果你有时间,你可以退房。我很感谢你的评论,所以有时候很好。我的意思是你发了一个问题,然后那个制造整个东西的人回答了。。。干杯@Howard Hinnant这确实是一个很棒的建议,特别是对于科学计算。这个库有没有可能变成C++17?它似乎已经在升级了(或者是打算升级)@vsoftco:谢谢你的评论。我不确定我是否能把它输入C++17。作为一项公开声明,如果有人想把它带到委员会,那也太好了。@HowardHinnant谢谢你的帮助。我试图建立一个基准
30ms
45[1/60]s
#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);
};