從RTTR談Reflection機制

雖然C++11引入了RTTI、Metaprogramming?等技術,但C++在Reflection編程方面依舊功能有限。在社區上,RTTR則提供了一套C++編寫的反射庫,補充了C++在Reflection方面的缺陷。

零、環境

操作系統Windows 11
Visual StudioVisual Studio Community 2022?
CMakeCMake 3.24.2
DoxygenDoxygen-1.9.8

一、下載源碼

從GitHub拉取RTTR代碼:

git clone https://github.com/rttrorg/rttr.git

二、編譯

按照下表配置CMake,并完成構建與生成,

Where is the source codeWindows 11
Where to build the binariesVisual Studio Community 2022?
CMAKE_INSTALL_PREFIXCMake 3.24.2

打開rttr.sln,構建"ALL_BUILD"完成RTTR編譯;構建"INSTALL"完成RTTR安裝。

三、RTTR源碼分析

雖然各種反射機制的具體實現有所不同,但大體思路還是一致的:

  • 生成類型元數據

類型元數據包括構造函數、屬性、方法等,類型元數據可以在編譯階段自動生成,也可以在運行階段手動注冊;

  • 執行反射

需要執行反射操作時,依據存儲的反射信息訪問對應的地址。

在RTTR中,類型元數據存儲在rttr::detail::class_data、rttr::detail::type_data中,

struct RTTR_LOCAL class_data
{class_data(get_derived_info_func func, std::vector<type> nested_types):   m_derived_info_func(func),m_nested_types(nested_types),m_dtor(create_invalid_item<destructor>()){}get_derived_info_func       m_derived_info_func;std::vector<type>           m_base_types;std::vector<type>           m_derived_types;std::vector<rttr_cast_func> m_conversion_list;std::vector<property>       m_properties;std::vector<method>         m_methods;std::vector<constructor>    m_ctors;std::vector<type>           m_nested_types;destructor                  m_dtor;
};
struct RTTR_LOCAL type_data
{type_data* raw_type_data;type_data* wrapped_type;type_data* array_raw_type;std::string name;string_view type_name;std::size_t get_sizeof;std::size_t get_pointer_dimension;impl::create_variant_func create_variant;impl::get_base_types_func get_base_types; // FIXME: this info should not be stored, its just temporarily,// thats why we store it as function pointerenumeration_wrapper_base*  enum_wrapper;impl::get_metadata_func    get_metadata;impl::create_wrapper_func  create_wrapper;impl::get_class_data_func  get_class_data;bool is_valid;RTTR_FORCE_INLINE bool type_trait_value(type_trait_infos type_trait) const RTTR_NOEXCEPT { return m_type_traits.test(static_cast<std::size_t>(type_trait)); }type_traits m_type_traits;
};

3.1 生成rttr::detials::type_data

當第一次調用type::get()函數時,會生成對應的類型元數據,

template<typename T>
RTTR_INLINE type type::get() RTTR_NOEXCEPT
{using non_ref_type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;return detail::create_or_get_type<non_ref_type>();
}template<typename T>
RTTR_LOCAL RTTR_INLINE enable_if_t<is_complete_type<T>::value, type>
create_or_get_type() RTTR_NOEXCEPT
{// when you get an error here, then the type was not completely defined// (a forward declaration is not enough because base_classes will not be found)using type_must_be_complete = char[ sizeof(T) ? 1: -1 ];(void) sizeof(type_must_be_complete);static const type val = create_type(get_registration_manager().add_item(make_type_data<T>()));return val;
}

?從中可以看出,rttr::type實際上時對類型數據的一種引用。

3.2 注冊類型信息數據

rttr::registration實際上時借助于函數對象rttr::registration::bind完成構造函數的注冊,

template<typename Class_Type>
template<typename F, typename acc_level, typename Tp>
registration::bind<detail::ctor_func, Class_Type, F, acc_level> registration::class_<Class_Type>::constructor(F func, acc_level level)
{using namespace detail;static_assert(is_functor<F>::value,"No valid accessor for invoking the constructor provided!");static_assert(std::is_same<return_func, typename method_type<F>::type>::value,"For creating this 'class type', please provide a function pointer or std::function with a return value.");return {create_if_empty(m_reg_exec), func};
}
template<typename Class_Type, typename F, typename acc_level>
class registration::bind<detail::ctor_func, Class_Type, F, acc_level> : public registration::class_<Class_Type>
{
//...    
public:bind(const std::shared_ptr<detail::registration_executer>& reg_exec, F func):   registration::class_<Class_Type>(reg_exec), m_reg_exec(reg_exec), m_func(func){m_reg_exec->add_registration_func(this);}template<typename... Args>registration::class_<Class_Type> operator()(Args&&... args){m_ctor = create_custom_constructor(m_func, std::forward<Args>(args)...);return registration::class_<Class_Type>(m_reg_exec);}
//...
}
registration_executer::~registration_executer()
{for (auto&& item : m_list){item.second();}
}

至于,屬性、方法等類型元數據的注冊,原理類似,可參照對應代碼。

3.3 生成對象

rttr::type調用存儲的構造器,完成對象的實例化。

variant type::create(vector<argument> args) const
{auto& ctors = m_type_data->get_class_data().m_ctors;for (const auto& ctor : ctors){if (detail::compare_with_arg_list::compare(ctor.get_parameter_infos(), args))return ctor.invoke_variadic(std::move(args));}return variant();
}

四、擴展:Reflection的其他實現

4.1 MFC

在MFC中,DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE宏用于聲明、定義反射相關元數據,

#define DECLARE_DYNAMIC(class_name) \
public: \static const CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#define DECLARE_DYNCREATE(class_name) \DECLARE_DYNAMIC(class_name) \static CObject* PASCAL CreateObject();#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \AFX_COMDAT const CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \RUNTIME_CLASS(base_class_name), NULL, class_init }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); }#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \CObject* PASCAL class_name::CreateObject() \{ return new class_name; } \IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \class_name::CreateObject, NULL)

從中,可以看到,反射元數據實際上時存放到了CRuntimeClass靜態變量中,

struct CRuntimeClass
{
// AttributesLPCSTR m_lpszClassName;int m_nObjectSize;UINT m_wSchema; // schema number of the loaded classCObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
#ifdef _AFXDLLCRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#elseCRuntimeClass* m_pBaseClass;
#endif// OperationsCObject* CreateObject();BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;// dynamic name lookup and creationstatic CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);static CObject* PASCAL CreateObject(LPCSTR lpszClassName);static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);// Implementationvoid Store(CArchive& ar) const;static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);// CRuntimeClass objects linked together in simple listCRuntimeClass* m_pNextClass;       // linked list of registered classesconst AFX_CLASSINIT* m_pClassInit;
};

4.2 Qt

在筆者<Qt源碼分析:QMetaObject實現原理>一文中,已就Qt反射機制做了分析,可以看到Qt反射相關元數據時存放到了QMetaObject中了,

struct Q_CORE_EXPORT QMetaObject
{//...struct { // private dataSuperData superdata;const QByteArrayData *stringdata;const uint *data;typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);StaticMetacallFunction static_metacall;const SuperData *relatedMetaObjects;void *extradata; //reserved for future use} d;//...
};

網絡資料

Reflectionicon-default.png?t=N7T8https://en.wikipedia.org/wiki/Reflection_%28computer_programming%29

The C++ Extensions for Reflection?icon-default.png?t=N7T8https://en.cppreference.com/w/cpp/experimental/reflect

RTTRicon-default.png?t=N7T8https://www.rttr.org/QMetaObjecticon-default.png?t=N7T8https://doc.qt.io/qt-5/qmetaobject.html

yazi-web?icon-default.png?t=N7T8https://github.com/kaifamiao/yazi-web.git

Boost Hana?icon-default.png?t=N7T8https://www.boost.org/doc/libs/1_80_0/libs/hana/doc/html/index.html

Boost PRF?icon-default.png?t=N7T8https://www.boost.org/doc/libs/master/doc/html/boost_pfr.html

?An Introduction to Reflection in C++icon-default.png?t=N7T8https://blog.csdn.net/qq_26221775/article/details/138768568?spm=1001.2014.3001.5501

FreeCAD: C++ Generic Factory Method inteface adviceicon-default.png?t=N7T8https://forum.freecad.org/viewtopic.php?p=24221&hilit=BaseClass#p24221

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13127.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13127.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13127.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

git 命令 - rebase

簡介 git rebase 是一個用于重新應用一系列提交到另一個基礎的 Git 命令。 它可以用來整合來自不同分支的更改&#xff0c;同時保持項目歷史的整潔。 操作流程 開始變基&#xff1a; 要開始一個變基操作&#xff0c;你需要指定一個基礎分支。通常&#xff0c;這個基礎分支是…

2024.05.14 Diffusion 代碼學習筆記

配環境 我個人用的是Geowizard的環境&#xff1a;https://github.com/fuxiao0719/GeoWizard。 出于方便考慮&#xff0c;用的pytorch官方的docker容器&#xff0c;因此python版本&#xff08;3.10&#xff09;和原作者&#xff08;3.9&#xff09;不同&#xff0c;其余都是一…

一文說通用戶故事點數是什么?

一文說通用戶故事點數是什么&#xff1f; 第26期&#xff1a;一文說通用戶故事點數是什么&#xff1f; 用戶故事點數是一種采用相對估算法進行估算的一種工具&#xff0c;一般采用斐波那契數列表征用戶故事里說的大小&#xff0c;采用0 1 2 3 5 8 13這樣的一些數字來表征用戶…

【漏洞復現】Secnet-智能路由系統 actpt_5g.data信息泄露

0x01 產品簡介 Secnet安網智能AC管理系統是廣州安網通信技術有限公司(簡稱“安網通信”)的無線AP管理系統 0x02 漏洞描述 Secnet智能路由系統 acipt 5g.data 接口存在信息泄露漏洞&#xff0c;未經身份驗證的遠程攻擊者可以利用此漏洞獲取系統賬戶名密碼等重要憑據&#xff…

全流程TOUGH系列軟件實踐技術應用

TOUGH系列軟件是由美國勞倫斯伯克利實驗室開發的&#xff0c;旨在解決非飽和帶中地下水、熱運移的通用模擬軟件。和傳統地下水模擬軟件Feflow和Modflow不同&#xff0c;TOUGH系列軟件采用模塊化設計和有限積分差網格剖分方法&#xff0c;通過配合不同狀態方程&#xff08;EOS模…

永磁同步電機的脈振高頻注入無速度傳感器simulink仿真模型

整理了永磁同步電機的脈振高頻注入無速度傳感器simulink仿真模型&#xff0c;該模型高頻注入仿真pmsm&#xff0c;無感控制&#xff0c;解決0速轉矩輸出問題&#xff0c;插入式永磁同步電機&#xff0c;凸極&#xff0c;高頻注入。MATLAB/simulink仿真&#xff0c;適合研究學習…

騰訊開源混元DiT文生圖模型,消費級單卡可推理

節前&#xff0c;我們組織了一場算法崗技術&面試討論會&#xff0c;邀請了一些互聯網大廠朋友、今年參加社招和校招面試的同學。 針對大模型技術趨勢、大模型落地項目經驗分享、新手如何入門算法崗、該如何準備面試攻略、面試常考點等熱門話題進行了深入的討論。 總結鏈接…

第七十八章 IIS 技術說明

文章目錄 第七十八章 IIS 技術說明IIS 應用程序池和Web Gardens應用程序池Web Gardens 應用程序池、Web花園和CSP 第七十八章 IIS 技術說明 對于那些有興趣使用 IIS 的人&#xff0c;此頁面介紹了應用程序池、網絡花園和位數。 IIS 應用程序池和Web Gardens 應用程序池 應用…

【AI+漫畫】程序員小李解決疑難雜癥BUG的日常

周末花了點時間制作的AI漫畫。 感慨一句&#xff0c;程序人生, 相伴隨行。 原文鏈接&#xff1a;【AI漫畫】程序員小李解決疑難雜癥BUG的日常

一物一碼數字化營銷進軍調味品行業,五豐黎紅“星廚俱樂部”火啦!

近日&#xff0c;由五豐黎紅聯合納寶科技精心打造的小程序“星廚俱樂部”火啦&#xff01;一經上線就吸引了大量用戶注冊和參與&#xff0c;可以說取得了非常成功的市場反饋&#xff0c;那究竟是一個什么樣的小程序&#xff0c;竟然有這么大的吸引力呢&#xff1f; 介紹小程序之…

武漢星起航:中國賣家借力亞馬遜跨境電商平臺,拓展全球銷售市場

隨著互聯網技術的飛速發展&#xff0c;跨境電商已成為連接全球消費者與賣家的重要橋梁。作為全球領先的跨境電商平臺&#xff0c;亞馬遜憑借其強大的品牌影響力、豐富的商品資源和高效的物流體系&#xff0c;為全球消費者提供了一個便捷、安全的購物環境。在這個平臺上&#xf…

連鎖收銀系統如何助力實體門店私域運營

作為實體門店&#xff0c;私域運營是提升客戶黏性和增加復購率的重要策略之一。而連鎖收銀系統在私域運營中扮演了關鍵的角色&#xff0c;它不僅可以幫助門店管理客戶信息和消費記錄&#xff0c;還能夠通過數據分析和營銷功能提供個性化的服務和推廣活動。下面看看連鎖收銀系統…

能源能耗管理系統

隨著全球對綠色、低碳、可持續發展理念的深入認識&#xff0c;企業對于能源的管理和節能降耗的需求日益迫切。在這一背景下&#xff0c;HiWoo Cloud平臺憑借其先進的能源能耗管理系統&#xff0c;為企業提供了一套高效、智能的解決方案&#xff0c;助力企業實現綠色節能&#x…

InfiniGate自研網關實現五

17.核心通信組件管理和處理服務映射 引入模塊api-gateway-core 到 api-gateway-assist 中進行創建和使用&#xff0c;并拉取自注冊中心的映射信息注冊到本地的網關通信組件中。 第17節是在第15節的基礎上繼續完善服務發現的相關功能&#xff0c;把從注冊中心拉取的網關映射信…

GPT3.5與GPT4.0的差別對比

隨著人工智能技術的飛速發展&#xff0c;GPT系列模型已成為自然語言處理&#xff08;NLP&#xff09;領域的翹楚。GPT3.5和GPT4.0作為這一系列的最新成員&#xff0c;各自在性能和應用上都有所突破。 GPT4.0預計將擁有數千億個參數&#xff0c;與前代GPT3.5相比&#xff0c;模…

ZYNQ之嵌入式驅動開發——字符設備驅動

文章目錄 Linux驅動程序分類Linux應用程序和驅動程序的關系簡單的測試驅動程序在petalinux中添加LED驅動新字符設備驅動 Linux驅動程序分類 驅動程序分為字符設備驅動、塊設備驅動和網絡設備驅動。 字符設備是按字節訪問的設備&#xff0c;比如以一個字節收發數據的串口&#…

軟信天成:業務流程管理驅動企業數字化轉型

近日&#xff0c;在國家發展改革委辦公廳、國家數據局綜合司聯合印發的《數字經濟2024年工作要點》中&#xff0c;明確強調了本年度大力推進重點領域數字化轉型&#xff0c;營造數字化轉型生態的戰略舉措&#xff0c;標志著國家對于企業數字化轉型的高度重視與積極倡導。 企業…

dubbo復習:(3) 服務超時時間配置

在dubbo admin中 可以進行類似如下配置 configVersion: v2.7 enabled: true configs:- side: consumeraddresses:- 0.0.0.0parameters:timeout: 55這樣配置之后&#xff0c;當服務端響應超過55毫秒時&#xff0c;在服務消費者的控制臺就會看到超時信息

(保姆級教程傻瓜式操作)樹莓派--基于opencv實現人臉識別

前言 因為當時沒有邊實驗邊記錄&#xff0c;所以這篇文章可能存在疏漏。不過很多地方我推薦了我參考過的博客或者視頻&#xff0c;希望盡可能地解答您的疑惑&#xff0c;如果您仍有不懂的地方&#xff0c;歡迎評論&#xff0c;如果我知道答案&#xff0c;我會很樂意為您解答。 …

私活更好用:SpringBoot開源項目!!【送源碼】

今天分享一款非常香的SpringBoot大屏開源項目&#xff0c;非常適合接私活用。 這是一款基于SpringBoot代碼生成器的快速開發平臺&#xff01;采用前后端分離架構&#xff1a;SpringBoot&#xff0c;Mybatis&#xff0c;Shiro&#xff0c;JWT&#xff0c;Vue&Ant Design。強…