问题描述
也许为了理解问题,我最好先展示代码。
#include <type_traits>
#include <functional>
#include <array>
template<size_t MaxSubscribers_,typename T>
struct Event
{
using Arg_T = T;
static constexpr size_t MaxSubscribers = MaxSubscribers_;
};
class EventManager
{
public: //Todo: needs to be made private
template<size_t MaxSubscribers,typename T>
struct subscriberMap
{
template<typename E,typename Valid = void>
struct events
{
};
template<typename E>
struct events<E,typename std::enable_if<std::is_base_of<Event<MaxSubscribers,T>,E>::value>::type>
{
static std::array<std::function<void(typename E::Arg_T)>,E::MaxSubscribers> list;
};
};
public:
template<typename E,size_t MaxSubscribers,typename Arg_T >
void subscribe(std::function<void(Arg_T)> callback) = delete;
template<template<size_t,typename> typename E,typename Arg_T>
void subscribe<E<MaxSubscribers,Arg_T>,MaxSubscribers,Arg_T>(std::function<void(Arg_T)> callback) // Error non-type partial specialization 'subscribe<E<MaxSubscribers,Arg_T>' is not allowed
{
subscriberMap<MaxSubscribers,Arg_T>::events<E>::list[0] = callabck;
}
};
template<size_t MaxSubscribers,typename T>
template<typename E>
std::array<std::function<void(typename E::Arg_T)>,E::MaxSubscribers>
EventManager::subscriberMap<MaxSubscribers,T>::events<E,E>::value>::type>::list{};
我有数据结构 Event
,它用于“索引”subscriberMap
,然后将函数添加到 list
。我想检查模板参数 E
是否是 Event
或其任何子类,仅当这是真的 list
是 events
的成员并且程序编译时。如果 E
不是事件,则程序不应编译。
要向 list
添加函数,请调用函数 subscribe
。 subscribe
需要知道最大订阅者数 MaxSubscribers
和参数的类型 Arg_T
,它将传递给 list
中的所有函数。此信息也在作为模板参数 E
传递的 Event 中。
问题是我必须有权访问 E
的成员,我的方法由于错误 non-type partial specialization 'subscribe<E<MaxSubscribers,Arg_T>' is not allowed
而不起作用,如果我没有专门化 {{1} 的模板}} 我无法访问 subscribe
。
这必须在没有堆分配的情况下完成,除了已经包含的头文件之外,没有库。
编辑
正如 this post 所说,我想用这个函数做的事情是不可能的。所以我决定只使用一个结构来包装这个函数。 这看起来像这样:
partial specialization
不幸的是,虽然编译器仍然给我一个错误 template<typename E,typename Valid=void>
struct Subscriptor
{
};
template<typename E>
struct Subscriptor<E,typename std::enable_if<std::is_base_of<Event<E::MaxSubscribers,typename E::Arg_T>,E>::value>::type>
{
void subscribe(std::function<void(typename E::Arg_T)> callback)
{
subscriberMap<E::MaxSubscribers,typename E::Arg_T>::events<E>::list[0] = callaback;
}
};
尚未定义,这意味着模板不够具体,无法阻止错误情况。
解决方法
不确定你想要什么,但语法是
template<template<size_t,typename> typename E,size_t MaxSubscribers,typename Arg_T>
void subscribe(std::function<void(Arg_T)> callback)
{
subscriberMap<MaxSubscribers,Arg_T>::template events<E<MaxSubscribers,Arg_T>>::list[0] = callback;
}
注意:template
之前需要 events<..>