Имеется множество примерно таких методов:
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<vlc_media_player_set_media>(__func__);
}
(*m_vlc_media_player_set_media)(p_mp, p_md);
}
Хочу сделать примерно такой макрос:
#define MF(t, x, name) if (!(x)) { (x) = m_libvlc_->Resolve<t>(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<t>(name); }
Не очень хорошо дружу с макросами, и не могу понять как такое реализовать.
Примечание: Имя поля всегда отличается от типа только добавочным m_
Ваш код
#define MF(t, name) if (!(m_#t)) { (m_#t) = m_libvlc_->Resolve<t>(name); }
почти правильный. Для token pasting («склеивания» токенов) нужно использовать удвоенный символ диеза.
#define MF(t, name) if (!(m_##t)) { (m_##t) = m_libvlc_->Resolve<t>(name); }
(Практически одновременно тот же совет в комментарии дал @VTT.)
Долой макросы! Даёшь шаблоны и вывод типов!
Предположу, что можно упростить код до следующего.
class /* имя класса, отвечающего переменной m_libvlc_ */ {
...
template <class T>
T& SafeGet(T*& member, const char* func) {
if (!member) {
member = Resolve<T>(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 в шаблоне, но такой вариант показался приятнее.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники