写了一个模板可变参数递归展开的反射,应该有性能问题,先记录下来放着

发布时间 2023-07-27 10:42:58作者: 马肯尼煤牙巴骨
#include <iostream>
#include <cstring>
#include <string>
using namespace std;

//预置
constexpr static inline unsigned  const_hash(char const* input)
{
    return *input ? static_cast<unsigned int>(*input) + 33 * const_hash(input + 1) : 5381;
}

template<int BUSI=0,auto P>
constexpr inline bool field_ignore() { return false;} 

template<auto P>
constexpr inline const char* field_name = nullptr;

template<auto P,auto...Ps>
struct field_do1
{
    template <int BUSI=0,class T,class L>
    static constexpr inline void run(T& obj,const char* fname,L&& lam) 
    {
        if constexpr(!field_ignore<BUSI,P>())
        if (const_hash(field_name<P>)== const_hash(fname))
            lam(obj.*P);
        if constexpr(sizeof...(Ps))
            field_do1<Ps...>::template run<BUSI>(obj,fname,std::move(lam));
    }
};

template<auto...Ps>
struct field_do0
{
    template <int BUSI=0,class T,class L>
    static constexpr inline void run(T& obj,const char* fname, L&& lam) 
    {
        field_do1<Ps...>::template run<BUSI>(obj,fname,std::move(lam));
    }
};

template<auto P,auto...Ps>
struct for_each1
{
    template <int BUSI=0,class T,class L>
    static constexpr inline void run(T& obj,L&& lam) 
    {
        if constexpr(!field_ignore<BUSI,P>())
        lam(field_name<P>,obj.*P);
        if constexpr(sizeof...(Ps) )
            for_each1<Ps...>::template run<BUSI>(obj,std::move(lam));
    }
};

template<auto...Ps>
struct for_each0
{
    template <int BUSI=0,class T,class L>
    constexpr static inline void run(T& obj, L&& lam) 
    {
        for_each1<Ps...>::template run<BUSI>(obj,std::move(lam));
    }
};

template<auto ... Ps>
struct fields_iterator
{
    template<int BUSI=0,class T,class L>
    constexpr static  inline void field_do(T& obj ,const char* fname,L&& lam)
    {
        field_do0<Ps...>::template run<BUSI>(obj,fname,std::move(lam)); 
    }
    template<int BUSI=0,class T,class L>
    constexpr static inline void foreach_do(T& obj ,L&& lam)
    {
        for_each0<Ps...>::template run<BUSI>(obj,std::move(lam)); 
    }
};



struct st {
    int f1 = 1;
    float f2 = 2.33;
    double f3 = 33.33;
};

//生成
template<> constexpr inline const char* field_name<&st::f1> = "f1";
template<> constexpr inline const char* field_name<&st::f2> = "f2";
template<> constexpr inline const char* field_name<&st::f3> = "f3";

using st_fields_iterator = fields_iterator<&st::f1,&st::f2,&st::f3>;

template<> constexpr inline bool field_ignore<1,&st::f1>() { return true;} 


//调用生成
int main() {
    st obj;

    std::string strf = "f";

    st_fields_iterator::field_do<1>(obj,(strf+"1").c_str(),[](auto&& value){
        value = 11113;
    });
    st_fields_iterator::field_do<1>(obj,(strf+"2").c_str(),[](auto&& value){
        value = 4.1456f ;
    });
    st_fields_iterator::field_do<1>(obj,(strf+"3").c_str(),[](auto&& value){
        value = 5.1456f ;
    });

    st_fields_iterator::foreach_do<1>(obj,[](const char* fname,auto&&value){
            std::cout << fname << " : " << value << std::endl;
    });

}