【问题标题】:Variadic templated container passing reference to contained items可变参数模板化容器传递对包含项目的引用
【发布时间】:2021-06-09 18:47:46
【问题描述】:

我正在尝试创建一个可变参数模板化容器,该容器将包含具有对容器的引用的项目。不幸的是,我不太清楚如何声明容器。 这是一个先有鸡还是先有蛋的问题。 Items 在 Container 上模板化,但 Container 也在 Items 上模板化。

我已尝试在下面提炼出相关代码。它抱怨没有声明“CollectionA”。

我怎样才能做到这一点?

#include <tuple>

template <typename CollectionT, typename Derived>
class ItemBase
{
public:
    ItemBase(CollectionT& c) : collection(c) {}

protected:
    CollectionT& collection;
};

template <typename CollectionT>
class ItemA : public ItemBase<CollectionT, ItemA<CollectionT> > {
    void aMethod() {
        this->collection.doSomething();
    }
};

template <typename CollectionT>
class ItemB : public ItemBase<CollectionT, ItemB<CollectionT> > {

};

template <typename ...Items>
class Collection
{
public:
    Collection() : items(*this) {}

    std::tuple<Items...> items;

    void doSomething() {}
};

int main( int, char** )
{
    // The Items are templated on the Collection, so how do I specify them?
    using CollectionA = Collection<ItemA<CollectionA>, ItemB<CollectionA>>;
    CollectionA collection;
}

【问题讨论】:

  • 这种设计看起来基本上是循环的,因为CollectionItems 成员,但Item 有一个Collection(参考)成员。
  • 是的,它是循环的,但常规的 CRTP 实现也是如此。 Derived 继承自 Base,后者在 Derived 上模板化。在这种情况下,一切都应该在编译时就知道了,所以我认为应该是可能的。

标签: c++ templates variadic-templates


【解决方案1】:

如果您确认所有Items 本身都有CollectionA 作为模板参数,为什么不传递模板?

template <template<typename>class... ItemTempls>
class Collection{
public:
    Collection() : items(*this) {}

    std::tuple<ItemTempls<Collection>...> items;

    void doSomething() {}
};

int main( int, char** ){
    using CollectionA = Collection<ItemA, ItemB>;
    CollectionA collection;
}

和CRTP类似,模板模板参数总是用来解决递归声明的问题。

【讨论】:

    【解决方案2】:

    这应该可以完成工作。

    #include <tuple>
    
    class CollectionBase
    {
    public:
        void doSomething() {}
    };
    
    class ItemBase
    {
    public:
        ItemBase(CollectionBase& c) : collection(c) {}
    
    protected:
        CollectionBase& collection;
    };
    
    template <typename ...Items>
    class Collection : CollectionBase
    {
    public:
        Collection() : items{Items{*this}...} {}
    
        std::tuple<Items...> items;
    };
    
    template <typename T>
    class Item : ItemBase
    {
    public:
        Item(CollectionBase& c) : ItemBase(c) {}
    
        void doSomething()
        {
            collection.doSomething();
        }
    };
    
    int main( int, char** )
    {
        Collection<Item<int>, Item<char>> collection;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-17
      • 1970-01-01
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 2015-06-08
      • 2011-11-15
      相关资源
      最近更新 更多