Code Monkey home page Code Monkey logo

static_reflect's Introduction

static_reflect

This is a fully compiling time static reflection lightweight framework for C++.

It provides a very rich compile-time reflection function.

Use it to put part of the serialization work at compile time(static_serilize.h)

Multiple inheritance,Raw C-style array and iterable container are supported for serialize.

environment

gcc10.3.0 & -std=c++20 & windows10

Below is a demo of all APIs.

#include"static_reflect.h"
#include"static_serialize.h"
#include<iostream>
#include<cstdio>
#include<sstream>
#include<vector>
#include<array>
using namespace refl;
using namespace seri;
using namespace std;
struct Node
{
	constexpr Node(){}
	constexpr Node(int x,float y):x{x},y{y}{} //不过构造函数还是得保持public...
	int x=3;
	float y=2;
	string_view z="default";
	constexpr int add(int dx,float dy)
	{
		return x+dx+y+dy;
	}
	constexpr int mul(float dx)
	{
		return x*dx*y;
	}
public:
	static consteval auto get_config() //注册反射所需的meta data
	{
		return Reflection<Node>::regist_class(
			Reflection<Node>::regist_field(
				pair{&Node::x,"x"_ss},
				pair{&Node::y,"y"_ss},
				pair{&Node::z,"z"_ss}
				),
			Reflection<Node>::regist_method(
				pair{&Node::add,"add"_ss},
				pair{&Node::mul,"mul"_ss}
				)
			);
	}
};
struct Test
{
	Node a;
	Node b;
	int c=2333;
	std::tuple<int,float,Node>tp;
	int*d=nullptr;
	std::array<int,5>e={1,2,3,4,5};
	int f[5]={5,4,3,2,1};
	constexpr Test()
	{
		a.x=23;
		a.y=43;
		a.z="abcd";
		d=new int(-5);
		std::get<0>(tp)=12;
		std::get<1>(tp)=24;
		std::get<2>(tp).z="sjf";
	}
	constexpr auto func(int,float,double){}
	static consteval auto get_config()
	{
		return Reflection<Test>::regist_class(
			Reflection<Test>::regist_field(
				pair{&Test::a,"a"_ss},
				pair{&Test::b,"b"_ss},				
  			    pair{&Test::c,"c"_ss},
				pair{&Test::tp,"tp"_ss},
				pair{&Test::d,"d"_ss},
				pair{&Test::e,"e"_ss},
				pair{&Test::f,"f"_ss}
				),
			Reflection<Test>::regist_method(
				pair{&Test::func,"func"_ss}
				)
			);
	}
};
struct Son:public Test
{
	string_view g="son";
	consteval static auto get_config()
	{
		return
			Reflection<Son>::Inherit<Test>::regist_class(
				Reflection<Son>::regist_field(
					pair{&Son::g,"g"_ss}
				),
				Reflection<Son>::regist_method(
					)
			);

	}
};

int main()
{

	constexpr auto reflect=static_reflect_v<Node>;  //获得记录反射信息的对象
	constexpr auto class_name=reflect.get_name();   //获得类名称
	static_assert(class_name=="Node");	
	
	constexpr auto fields=reflect.get_fields();      //所有属性的反射信息
	constexpr auto field=fields.get_field("x"_ss);   //名称为x的属性
	static_assert(fields.size()==3);                 //这个类有3个属性
	static_assert(field.get_name()=="x");            //属性名称
	static_assert(field.get_type_name()=="int");     //属性类型名称
	static_assert(fields.get_field("y"_ss).get_type_name()=="float");
	static_assert(fields.get_field("z"_ss).get_type_name()=="std::basic_string_view<char>");
	
	constexpr auto methods=reflect.get_methods();  //获得记录方法的反射信息的对象
	constexpr auto method=methods.get_method("add"_ss);
	
	static_assert(methods.size()==2);              //方法的数量
	static_assert(method.get_name()=="add");       //方法名称为add
	
	static_assert(method.get_type_name()=="int (Node::*)(int, float)"); //函数指针类型
	static_assert(method.get_return_type_name()=="int");                //返回值
	static_assert(method.get_args_type_name_list()==std::array<std::string_view,2>{"int","float"});	//函数形参
	static_assert(method.get_args_type_name<0>()=="int");
	static_assert(method.get_args_type_name<1>()=="float");

	constexpr auto object=reflect.get_instance(1,2.f);    //调用构造函数
	constexpr auto object2=reflect.get_instance();        //调用构造函数
	static_assert(field.get_value(object)==1);
	static_assert(method.constexpr_invoke(object,2,3.f)==8);
	static_assert(method.constexpr_invoke(object2,2,3.f)==10);

	fields.for_each([](auto&&index,auto field){
		cout<<field.get_type_name()<<" "<<field.get_name()<<endl;
	});
	
	methods.for_each([](auto&&index,auto method){
		cout<<method.get_type_name()<<" "<<method.get_name()<<endl;
	});
	

	auto object1=reflect.get_instance(1,2.f);    
	cout<<field.get_value(object1)<<endl;
	cout<<object1.x<<endl;
	field.set_value(object1,72);
	cout<<object1.x<<endl;
	cout<<method.invoke(object1,2,3.f)<<endl;

	
	using reflect_t=static_reflect_t<Node>;                //反射信息类型
	using fields_t=reflect_t::fields_t;                    //所有的属性信息类
	constexpr auto fsize_v=fields_t::size_v;               //属性数量
	using field_t=fields_t::field_ss_t<decltype("x"_ss)>;  //名称为x的属性
	using type=field_t::type;
	static_assert(std::is_same_v<type,int>);               //属性的类型为int
	static_assert(fsize_v==3);                            
	static_assert(field_t::name_v=="x");
	
	static_assert(static_reflect_t<Node>::fields_t::field_t<1>::name_v=="y");           //按照下标来访问元素
	static_assert(is_same_v<static_reflect_t<Node>::fields_t::field_t<1>::type,float>); //按照下标来访问元素
	
	static_assert(1==fields_t::has_field_v<decltype("x"_ss)>);   //检测名称为x的属性是否存在
	static_assert(1==fields_t::has_field_v<decltype("y"_ss)>);
	static_assert(0==fields_t::has_field_v<decltype("xxx"_ss)>);

	
	using reflect_t=static_reflect_t<Node>;
	using methods_t=reflect_t::methods_t;                      //所有的方法的编译期反射信息类
	using method_t=methods_t::method_ss_t<decltype("add"_ss)>; //名称为add的属性
	using return_t=method_t::return_t;                         //返回值类型
	constexpr auto num_params=method_t::size_v;                //参数个数
	
	using param0_t=method_t::parameter_t<0>;                   //具体的每个形参类型
	using param1_t=method_t::parameter_t<1>;

	static_assert(method_t::name_v=="add");              //该属性名称为add
	static_assert(methods_t::size_v==2);                 //属性个数为2
	static_assert(num_params==2);                        //add属性的形参数量为2
	static_assert(is_same_v<param0_t,int>);
	static_assert(is_same_v<param1_t,float>);            //每个形参具体类型
	static_assert(is_same_v<return_t,int>);              //返回值类型
	
	static_assert(1==methods_t::has_method_v<decltype("add"_ss)>); //检测名称为add的方法是否存在
	static_assert(1==methods_t::has_method_v<decltype("mul"_ss)>);
	static_assert(0==methods_t::has_method_v<decltype("func"_ss)>);
	
	
	constexpr auto d1=describe_v<Node>;
	constexpr auto d2=describe_v<Test>;
	cout<<d1<<endl<<d2<<endl;
	
	
	constexpr auto d3=describe_v<Son>;
	cout<<d3<<endl;
	
	
	constexpr auto name=get_type_name_v<
		static_reflect_t<Son>::methods_t::method_ss_t<decltype("func"_ss)>::return_t
	>;
	cout<<name;
	
	
	Son obj;
	cout<<seri::dumps(obj); 
	
}

static_reflect's People

Contributors

shijunfeng00 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.