c++ - 将可变参数模板参数包解包到函数签名中
问题描述
我在一个小型库中创建了用于调度和处理事件的类。我的目标是让它尽可能易于使用,避免宏观污染。事件在编译时注册,监听器在运行时订阅事件。两者都由Resource
命名空间中的枚举标识。Pack
是可变参数模板参数的存储。EventInfo
是告诉我们将在Listener
和中使用哪些参数的方法Event
。代码:
namespace Resource
{
enum class Resource::EventId;
enum class Resource::ListenerId;
}
template< class EventId, EventId id >
struct EventInfo;
template< class... Args >
struct Pack
{
};
template< class ListenerId_, class... EventData >
struct Listener
{
using ListenerId = ListenerId_;
ListenerId Id = ListenerId::Undefined;
bool IsEnabled = false;
std::function< void( EventData... ) > Callback = nullptr;
};
template< class ListenerId_, class... EventData >
struct EventInfoHelper
{
using Data = Pack< EventData... >;
using Listener = typename Listener< ListenerId_, EventData... >;
using ListenerId = typename Listener::ListenerId;
};
#define REGISTER_EVENT_W_ARGS( NAME, ... ) \
template<> \
struct EventInfo< Resource::EventId, Resource::EventId::NAME > \
{ \
public: \
using Hlpr = EventInfoHelper< Resource::ListenerId, __VA_ARGS__ >; \
using Data = Hlpr::Data; \
using Listener = Hlpr::Listener; \
using ListenerId = Hlpr::ListenerId; \
};
REGISTER_EVENT_W_ARGS( OnUpdate, const sf::Time& );
// ... macro undef here
template< class Id, Id id >
class Event
{
public:
using Data = typename EventInfo< Id, id >::Data;
using Listener = typename EventInfo< Id, id >::Listener;
using ListenerId = typename EventInfo< Id, id >::ListenerId;
template< class... DataUnpacked, class = std::enable_if_t< std::is_same< Pack< DataUnpacked... >, Data >::value > >
static void Dispatch( DataUnpacked... data )
{
for( auto& listener : m_listeners )
{
CHECK( listener.Id != ListenerId::Undefined );
if( listener.IsEnabled )
{
CHECK( listener.Callback != nullptr );
listener.Callback( data... );
}
}
}
// ...
private:
static std::vector< Listener > m_listeners;
};
当前用例:
Event< Resource::EventId, Resource::EventId::OnUpdate >::Dispatch< const sf::Time& >( dt );
期望(从 中扣除参数EventInfo::Data
):
Event< Resource::EventId, Resource::EventId::OnUpdate >::Dispatch( dt );
问题是如何Dispatch
使用注册EventInfo::Data
为Pack< Args... >
参数的参数来实现?
解决方案
您提供的代码不完整,因此我无法将解决方案集成到您的示例中。
您可以使用基类从 Pack<...> 中提取参数包并将其扩展为基类中的函数
template<typename ...>
class Pack {};
template<typename>
class test_base;
template<typename ... Args>
class test_base<Pack<Args...>> {
public:
void Dispatcher(Args... args) {
//implemntation
}
};
template<typename ... Args>
class test : public test_base<Pack<Args...>> {
};
推荐阅读
- c++ - 在 Cloud9 中运行 OpenCV 项目
- bootstrap-vue - 绑定到 b 表字段的变量
- r - 如何将字符串“2019-10-09T06:07:05.888Z”转换为日历日期和时间
- javascript - 在我的阵列上使用 axios 发送数据的问题
- aws-sdk - Quicksight 刷新 Anomaly 仪表板以获取实时数据
- powershell - 检查 TCP 连接数
- react-native - react-native-document-picker:在 react native 0.61.2 中调用 document picker.show 时键入错误 - >未定义的文档选择器
- python - 使用python将文件上传到共享点
- android - 尝试在空对象引用上调用虚拟方法“void android.view.ViewGroup.transformMatrixToLocal(android.graphics.Matrix)”
- flutter - 使用动态对象时如何让 Radio 处理颤振?