首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11可变模板模板参数

C++11可变模板模板参数
EN

Stack Overflow用户
提问于 2012-02-15 22:41:17
回答 2查看 3K关注 0票数 6

保留原来的问题。请参阅下面的解决方案。这可能是一些简单的东西,但仍然。我有以下C++11代码片段:

代码语言:javascript
复制
#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继承以typelist中的每个类型为模板的EventContainer。我可以使用Loki::library来做这件事,但是我想使用带有可变模板的C++11。谢谢。

Resolution1:修复EventStorage模板问题。这将使EventStorage,多个继承所有的EventContainer模板与每种类型的Ts

代码语言:javascript
复制
template <typename...>
class EventStorage
{
};

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

};

现在,我在下面的main()中遇到了编译时错误

代码语言:javascript
复制
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。

Resolution2:正如@Matthieu M.建议的那样,我可以在EventStorage中提供一个转发方法,但代价是调用一个额外的函数:

代码语言:javascript
复制
template <typename T>
void push(const T& t)
{
    EventContainer<T>::push(t);
}

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-02-15 22:57:27

一开始引入typelist有什么原因吗?

代码语言:javascript
复制
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;
}

这个works,你可以typedef整个Storage<...>位。

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

有两种解决方案:

代码语言:javascript
复制
template <typename...> struct CombineStorage;

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

或者简单地提供一个打字员适配器:

代码语言:javascript
复制
template <typename... Args>
class Storage<typelist<Args...>>: public Storage<Args...> {};
票数 6
EN

Stack Overflow用户

发布于 2012-02-15 23:15:21

目前,您甚至还没有向EventStorage传递类型表实例化,只传递了类型表模板。因此,目前还没有可以扩展的类型包。

但是,您应该能够使用专门化来解压typelist,并在其他情况下使用类型包:

代码语言:javascript
复制
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,但它需要精确的类型匹配。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9295387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档