簡體   English   中英

在chrono中獲取時間類型的名稱

[英]Get the name of a time type in chrono

假設我有一個測量類的時間,可以通過這樣的持續時間類型進行參數化

template<typename TimeT = std::chrono::milliseconds>
struct measure
{ /* implementation */ };

我想要的是能夠打印出TimeT 我傾向於實現這樣的靜態成員函數:

static string TimeType() const; 

我的問題是:

  1. 我應該添加會員嗎? 這不應該是靜態的嗎?
  2. 如何實施這個體制? 我應該使用依賴於實現的非編譯時typeinfo / name組合(在這種情況下我必須刪除上面的constexpr )或者我應該選擇創建幾個特殊化,這些特殊化將返回每種時間類型的正確字符串?
  3. 是否有更標准/慣用的方式來獲取時間類型的名稱?

歡迎您使用我的<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";        };

durationtime_point都有一個類型為ratioperiod成員,表示該類型的每個tick的秒數。

我不相信C ++標准提供了一種將10特殊權力轉換為公制前綴的方法; 你必須為此推出自己的功能。 但請注意,這段時間不一定是標准時期; 用戶可以根據他們喜歡的任何時期(例如年)或甚至標准時段創建時間測量,但使用不同的表示類型(例如, double ),因此您可能不應該假設。 為什么不把它作為另一個參數?

您要做的是反射定義的一部分,更具體地說是運行時類型信息( RTTI ),它使代碼能夠在運行時自行檢查,我在嘗試制作時對此進行了很好的研究。將傳入類型的所有成員變量序列化為{ "varName"=<varValue> }等格式的系統

不幸的是,簡單的答案是C ++本身不支持反射,並且它提供“類似”功能(即<type_traits>typeid() ),它還有很多不足之處。 最好的結果將來自生成您需要的數據的自定義構建步驟,我決定反對這種方法,因此在這種情況下無法真正幫助“如何”,但這些方法顯然在可移植性方面受到限制。

然而,您已經提到過的模板特化方法是邁向C ++運行時反射的最佳實現的一步,C ++運行時反射使用宏的組合來生成類描述符。

MFC宏DECLARE_DYNAMICIMPLEMENT_DYNAMIC是為您的類創建這些描述符之一所需的所有污染,然后添加函數IsKindOf()GetRuntimeClass() ,最有用的通常是GetRuntimeClass() ,它返回CRuntimeClass

要實現類似的東西,你可以使用類似的東西;

#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在書中寫的文章“在C ++中使用模板反射”編程寶石5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM