Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Использование в макросах строковых литералов в качестве типов

#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; }

Комментариев нет:

Отправить комментарий