【发布时间】:2021-09-24 23:47:56
【问题描述】:
如果我先显示代码,也许最好能理解问题。
#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, size_t MaxSubscribers, 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>, 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, typename std::enable_if<std::is_base_of<Event<MaxSubscribers, T>, E>::value>::type>::list{};
我有数据结构Event,它用于“索引”subscriberMap,然后将函数添加到list。我想检查模板参数E 是Event 还是它的任何子类,只有当这是真的list 是events 的成员并且程序编译时。如果E 不是事件,则程序不应编译。
要向list 添加函数,请调用函数subscribe。 subscribe 需要知道MaxSubscribers 的最大订阅者数量和参数的类型,Arg_T,将传递给list 中的所有函数。此信息也在作为模板参数E 传递的事件中。
问题是我必须访问E 的成员,由于non-type partial specialization 'subscribe<E<MaxSubscribers, Arg_T>, MaxSubscribers, Arg_T>' is not allowed 错误,我的方法不起作用,如果我不专门化subscribe 的模板我无法访问list.
这必须在没有堆分配和库的情况下完成,除了已经包含的头文件。
编辑
我实际上找到了一种方法来消除partial specialization 错误。
正如this post 所说,我想用这个功能做的事情是不可能的。所以我决定只使用一个结构来包装函数。 这看起来像这样:
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;
}
};
不幸的是,尽管编译器仍然给我一个 list 尚未定义的错误,这意味着模板不够具体,无法阻止错误情况。
【问题讨论】:
标签: c++ c++11 templates types metaprogramming