#cpp #препроцессор
Имеется множество примерно таких методов: void libvlc::Interop::LibVLCHelper::libvlc_media_player_set_media(libvlc_media_player_t * p_mp, libvlc_media_t * p_md) { if (!m_vlc_media_player_set_media) { m_vlc_media_player_set_media = m_libvlc_->Resolve(__func__); } (*m_vlc_media_player_set_media)(p_mp, p_md); } Хочу сделать примерно такой макрос: #define MF(t, x, name) if (!(x)) { (x) = m_libvlc_->Resolve (name); } И определение на валидность упрощается соответственно до такого вида: libvlc_media_player_t * libvlc::Interop::LibVLCHelper::libvlc_media_player_new(libvlc_instance_t * p_instance) { MF(vlc_media_player_new, m_vlc_media_player_new, __func__); return (*m_vlc_media_player_new)(p_instance); } Да, он работает, но можно ли улучшить макрос до примерно такого вызова? libvlc_media_player_t * libvlc::Interop::LibVLCHelper::libvlc_media_player_new(libvlc_instance_t * p_instance) { MF(vlc_media_player_new, __func__); return (*m_vlc_media_player_new)(p_instance); } Для понятия: Макрос принимает тип, 1м параметром, подставляет m_(тут тип), и вид примерно такой: #define MF(t, name) if (!(m_#t)) { (m_#t) = m_libvlc_->Resolve (name); } Не очень хорошо дружу с макросами, и не могу понять как такое реализовать. Примечание: Имя поля всегда отличается от типа только добавочным m_
Ответы
Ответ 1
Ваш код #define MF(t, name) if (!(m_#t)) { (m_#t) = m_libvlc_->Resolve(name); } почти правильный. Для token pasting («склеивания» токенов) нужно использовать удвоенный символ диеза. #define MF(t, name) if (!(m_##t)) { (m_##t) = m_libvlc_->Resolve (name); } (Практически одновременно тот же совет в комментарии дал @VTT.) Ответ 2
Долой макросы! Даёшь шаблоны и вывод типов! Предположу, что можно упростить код до следующего. class /* имя класса, отвечающего переменной m_libvlc_ */ { ... templateT& SafeGet(T*& member, const char* func) { if (!member) { member = Resolve (func); } return *member; } } Использование: void libvlc::Interop::LibVLCHelper::libvlc_media_player_set_media(libvlc_media_player_t * p_mp, libvlc_media_t * p_md) { m_libvlc_->SafeGet(m_vlc_media_player_set_media, __func__)(p_mp, p_md); } Ну и если всё-таки хочется макрос.. #define SAFE_GET(member) m_libvlc_->SafeGet(member, __func__) и void libvlc::Interop::LibVLCHelper::libvlc_media_player_set_media(libvlc_media_player_t * p_mp, libvlc_media_t * p_md) { SAFE_GET(m_vlc_media_player_set_media)(p_mp, p_md); } P.S. Можно добавить в этот вызов и аргументы через class ...Args в шаблоне, но такой вариант показался приятнее.
Комментариев нет:
Отправить комментарий