#cpp #шаблоны_с++ #макросы #рефлексия
В классе есть метаинформация, представленная в виде вектора пар значений строка-строка, которые представляют собой строковое представление типа и имени члена класса. Напрмиер: class TObject { private: int t_fMember; char t_sMember; }; Для данного класса метаинформация представляется следующим множеством пар: { {"int", "t_fMember"}, {"char","t_sMember"} } Есть макрос, которые скрывает за собой шаблонную ф-ию: #define GET_MEMBER_VALUE( MEM_TYPE, ... ) \ template\ MEM_TYPE RetVal(...)\ {\ \ } В сигнатуре и возвращаемом типе шаблонной ф-ии я писал не MEM_TYPE, а ##MEM_TYPE, надеясь, что, например "int" превратится в int, однако, этого не произошло (чего и следовало ожидать). Есть ли способ проводить подобную конверсию ? Передавать тип как строковый литерал, а затем делать обратное преобразование ? ("type" -> type) UPD0: как бы я хотел это использовать: #define GET_MEMBER_VALUE( MEM_TYPE, MEM_NAME, PTR_TO_OBJECT ) \ template \ MEM_TYPE RetVal(...)\ {\ return PTR_TO_OBJECT->##MEM_NAME; \ } Отдаем указатель на объект, тип члена и его имя, обращаемся оператором -> к члену по имени и возвращаем его значение.
Ответы
Ответ 1
Очевидно, из строки с именем нельзя получить указатель на член класса, просто потому что в предложенной схеме хранения метаинформации отсутствую указатели на члены классов. Более развитые системы хранения метаинформации (например, BOOST.FUSION) это умеют. #include#include #include #include #include #include #include struct TObject { int t_fMember; char t_sMember; } ; BOOST_FUSION_ADAPT_STRUCT( TObject, (int , t_fMember) (char, t_sMember) ); template struct memberByNameVisitor { ObjectType* ptr; const char* seek_name; ReturnType** result; template void visit_field( const char* field_name, T& field_value ) const {} void visit_field( const char* field_name, ReturnType& field_value ) const { if( strcmp( seek_name, field_name) ==0 ) *result = & field_value; } template void operator() (Index idx) const { visit_field( boost::fusion::extension::struct_member_name ::call(), boost::fusion::at (*ptr) ); } }; template ReturnType& memberByName( ObjectType& ref, const char* name ) { typedef boost::mpl::range_c ::value > Indices; ReturnType* result=nullptr; memberByNameVisitor visitor={&ref, name, &result}; boost::fusion::for_each( Indices(), visitor ); if(result!=nullptr) return *result; else throw std::invalid_argument("Filed is not found"); } int main(int argc, char *argv[]) { TObject test ={ 1234, 'A' }; std::cout << memberByName ( test, "t_fMember" ) << std::endl; memberByName (test, "t_sMember") = 'C'; std::cout << memberByName (test, "t_sMember") << std::endl; return 0; }
Комментариев нет:
Отправить комментарий