C++ 在chrono中获取时间类型的名称

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),还是选择创建几个专门化,以返回每个时间类

假设我有一个时间测量类,可以通过如下的duration类型进行参数化

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);
    };