簡體   English   中英

構造不同類型的C ++向量數組

[英]Constructing array of C++ vectors of different types

有沒有一種很好的方法來構造不同類型的std :: vector數組? 還有存儲這些向量的好方法嗎?

例如,讓我們有一些結構FooBarBaz 我想制作一個容器類Cont ,其中包含FooBarBaz向量的某種組合。 以下代碼將實現此目的,但是我有一些問題。

#include <vector>

// arbitrary structs
struct Foo{ int var1; };
struct Bar{ double var1; double var2; };
struct Baz{ char var1; float var2; };

enum Mask{
    fooMask = (1<<0),
    barMask = (1<<1),
    bazMask = (1<<2)
};

class Cont{
    void** containers;

public:
    Cont(int mask){
        // count number of 1s in mask
        int count = 0;
        int countMask = mask;
        while(countMask){
            countMask &= countMask-1; // unset rightmost 1
            count++;
        }

        containers = new void*[count];

        int index = 0;
        if((mask & fooMask) == fooMask)
            containers[index++] = new std::vector<Foo>;
        if((mask & barMask) == barMask)
            containers[index++] = new std::vector<Bar>;
        if((mask & bazMask) == bazMask)
            containers[index++] = new std::vector<Baz>;
    }
};

int main(){
    // example construction
    Cont c1(fooMask);
    Cont c2(barMask|bazMask);

    return 0;
}

首先,我不喜歡將向量數組存儲在void **中,但是我找不到更好的方法。

其次,如果我添加一個名為Qux的新結構,則必須修改Cont構造函數。 最好是出於可維護性,我希望構造數組而不必將結構類型硬編碼到Cont類中。

我試圖使用模板來解決此問題,但是找不到我滿意的解決方案。 我擔心讓Cont成為模板,因為我認為這會導致每個結構組合的模板膨脹。 另外,我將有多個Cont對象,但僅需要一種組合。

您可以使用類型擦除。

struct ContainerBase
{
  virtual ~ContainerBase() = 0;
  // This is where you can add an interface for common functionality.
  // Write the pure virtual functions here and implement/override them in ContainerTyped.
};

inline ContainerBase::~ContainerBase() = default;

template<class T>
struct ContainerTyped : public ContainerBase
{
  std::vector<T> values;
};

class Cont
{
  std::vector<std::unique_ptr<ContainerBase>> containers;

public:
  Cont(int mask) {
    // ...
    if ((mask & fooMask) > 0)
      containers.push_back(std::make_unique<ContainerTyped<Foo>>());
    if ((mask & barMask) > 0)
      containers.push_back(std::make_unique<ContainerTyped<Bar>>());
  }
};

演示版

這可能比使用例如std::any或其他先前存在的類型擦除更合適,因為1)您指定只能存儲特定的東西(您的矢量容器),並且2)您可以按照指示添加通用接口,甚至專門接口函數在不同的ContainerTyped 但是我們需要更多地了解您的用例,以詳細說明這種好處。

void*的問題始終是,由於要繞過強類型系統,因此您始終需要以某種方式保留有關實際存儲內容的信息。 換句話說,如何將存儲的東西返回到強類型系統中? 這正是上述方法可以發揮作用的部分,因為您可以在ContainerBase添加一個virtual print() = 0 ,然后為每種結構創建專用版本,例如

template<>
void ContainerTyped<Foo>::print()
{
    for (Foo& foo : values) {
        // Print Foo objects as you wish!
    }
}

就添加Qux結構時不必觸摸Cont構造函數而言,您顯然仍然需要以某種方式編碼“哪個掩碼位屬於哪個結構”的信息,但是您可以從Cont構造函數中提取它(甚至將其隱藏)在不同的翻譯單元中):

// Put this implementation wherever, Cont only has to know the signature.
std::unique_ptr<ContainerBase> makeContainer(int mask, unsigned indexBit)
{
  if ((mask & fooMask) > 0)
    return std::make_unique<ContainerTyped<Foo>>();
  // etc.
  if ((mask & quxMask) > 0)
    return std::make_unique<ContainerTyped<Qux>>();
  return nullptr;
}

// ...

Cont::Cont(int mask)
{
  for (unsigned indexBit = 0; indexBit < 8; ++indexBit) {
    auto container = makeContainer(mask, indexBit);
    if (container)
      containers.emplace_back(std::move(container));
  }
}

您可以采用其他方式來枚舉枚舉->類型信息,但這超出了此問題的范圍。 關鍵是您可以將具體類型隱藏在ContainerBase后面,並在要引用“這些容器中的任何一個”的地方使用該類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM