6

保留旧问题。解决方法见下文。这可能很简单,但仍然如此。我有以下 C++11 代码片段:

#include <vector>

template <typename... Ts>
struct typelist
{
};

template <typename T>
struct EventContainer
{
    typedef T Type;
    /// TODO. Ring buffer
    std::vector<T> container;

    void push(const T& t)
    {
        EventContainer<T>::container.push_back(t);
    }

    virtual ~EventContainer()
    {
    }
};


template <template <typename...> class TL>
class EventStorage:
        public EventContainer<Ts>...
{

};

class Event1
{
};

class Event2
{
};

typedef typelist<Event1,Event2> Events12;

int main()
{
    EventStorage<Events12> ev;

    return 0;
}

如何EventStorage使用. EventContainer_ typelist我可以使用 Loki:: library 来完成,但我想将 C++11 与可变参数模板一起使用。谢谢你。

解决方案 1:修复EventStorage模板模板问题。这将使EventStorage多个继承所有EventContainer模板化的每个类型的Ts.

template <typename...>
class EventStorage
{
};

template <typename... Ts>
class EventStorage < typelist<Ts...> >:
        public EventContainer<Ts>...
{

};

现在我有编译时错误,如下main()

int main()
{
    EventStorage<Events12> ev;
    Event1 ev1;
    ev.push(ev1);

    return 0;
}

In function ‘int main()’:
error: request for member ‘push’ is ambiguous
error: candidates are: void EventContainer<T>::push(const T&) [with T = Event2]
error: void EventContainer<T>::push(const T&) [with T = Event1]

为什么编译器会感到困惑?毕竟我用特定的类型推送。GCC 4.6.1 在这里。

解决方案2:正如@Matthieu M. 建议的那样,我可以提出一个转发方法 int EventStorage,但代价是一个额外的函数调用:

template <typename T>
void push(const T& t)
{
    EventContainer<T>::push(t);
}

根据 Alexandrescu 的说法,只要参数是引用,编译器就会优化这个前向调用。现在问题正式结束:)

4

2 回答 2

6

typelist首先引入 有什么理由吗?

template <typename T> struct Template { void push(T) {} };

template <typename... Args>
class Storage: public Template<Args>...
{
public:
  // forwarding...
  template <typename T>
  void push(T t) {
    Template<T>& me = *this;
    me.push(t);
  }
};

int main() {
  Storage< int, char > storage;
}

行得通,你可以做到typedefStorage<...>一点。

编辑:关注关于“组合”类型可能性的评论。

有两种解决方案:

template <typename...> struct CombineStorage;

template <typename... A, typename... B>
struct CombineStorage<Storage<A...>, Storage<B...>> {
  typedef Storage<A..., B...> type;
};

或者简单地提供一个类型列表适配器:

template <typename... Args>
class Storage<typelist<Args...>>: public Storage<Args...> {};
于 2012-02-15T14:57:26.780 回答
1

目前,您甚至从未将 typelist 实例传递给 EventStorage,而只是 typelist template。所以目前,没有类型包可以扩展。

但是,您应该能够使用专业化解包类型列表,否则可以使用类型包:

template <typename...> class EventStorage;

template <typename Head, typename... Tail> class EventStorage<Head, Tail...>
  : public EventContainer<Head>, EventStorage<Tail...>
{
  using EventContainer<Head>::push;
  using EventStorage<Tail...>::push;
};

// allows you to pass typelists for convenience
template <typename... TL> class EventStorage<typelist<TL...>>
  : public EventStorage<TL...>
{
  using EventStorage<TL...>::push;
};

using声明只是将所有方法拉push入同一个重载集,这似乎对我有用。

另一种方法是添加一个显式转发到的模板方法(可能只是顶级类型列表专业化)this->EventContainer<T>::push,但它需要精确的类型匹配。

于 2012-02-15T15:15:20.943 回答