发出带有类型和值的专用模板

问题描述 投票:0回答:1

我写了以下课程

#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;
模板匹配吗?

c++ templates template-specialization
1个回答
0
投票

这是因为您的主模板是这样声明的:

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;
};
© www.soinside.com 2019 - 2024. All rights reserved.