我写了以下课程
#include <tuple>
class AbstractEvent
{
public:
using ID = int;
public:
virtual ~AbstractEvent() = default;
ID id() const { return id_; }
protected:
explicit AbstractEvent(ID id) : id_(id) {}
private:
ID id_;
};
template <AbstractEvent::ID ID_>
class Event : public AbstractEvent
{
public:
static constexpr auto kID = ID_;
Event() : AbstractEvent(kID) {}
};
template <typename T, typename ... ARGS>
class BasicEvent;
template <AbstractEvent::ID ID_, typename ... ARGS>
class BasicEvent<Event<ID_>, ARGS...> : public Event<ID_>
{
public:
explicit BasicEvent(ARGS... args) : _args(std::move(args)...) {}
~BasicEvent() = default;
template <unsigned int INDEX_ = 0>
inline const auto& arg() const
{
return std::get<INDEX_>(_args);
}
template <unsigned int INDEX_ = 0>
inline auto& arg()
{
return std::get<INDEX_>(_args);
}
private:
std::tuple<ARGS...> _args;
};
struct Events
{
enum : AbstractEvent::ID
{
Event1ID,
Event2ID,
};
using Event1 = Event<Event1ID>;
using Event2 = Event<Event2ID>;
};
我的目标是特殊
BasicEvent
模板,以便我可以像这样向其传递“事件 ID”值或 Event
类
class Event1 : public BasicEvent<Events::Event1ID> {};
或
class Event1 : public BasicEvent<Events::Event1> {};
但是,第一个示例(使用 ID)会导致 CLang 上出现以下编译错误:
template argument for template type parameter must be a type
以及海湾合作委员会
type/value mismatch at argument 1 in template parameter list for 'template<class T, class ... ARGS> class BasicEvent'
这对我来说没有意义。如果我专门使用
BasicEvent
类来获取值,那么 BasicEvent<Event<ID_>, ARGS...>
不应该与 template <typename T, typename ... ARGS> class BasicEvent;
模板匹配吗?
这是因为您的主模板是这样声明的:
template <typename T, typename ... ARGS>
class BasicEvent;
由于该模板采用类型并且无法直接引用专业化,因此您必须向其发送类型:
class Event1 : public BasicEvent<Event<Events::Event1ID>> {};
这将正确匹配您的专业。
另一方面,如果您只想处理事件 ID,您可以这样更改模板:
// Remove this
//template <typename T, typename ... ARGS>
//class BasicEvent;
template <AbstractEvent::ID ID_, typename ... ARGS>
class BasicEvent : public Event<ID_>
{
public:
explicit BasicEvent(ARGS... args) : _args(std::move(args)...) {}
~BasicEvent() = default;
template <unsigned int INDEX_ = 0>
inline const auto& arg() const
{
return std::get<INDEX_>(_args);
}
template <unsigned int INDEX_ = 0>
inline auto& arg()
{
return std::get<INDEX_>(_args);
}
private:
std::tuple<ARGS...> _args;
};