如何创建一个包含三种不同类型矢量的矢量

时间:2018-06-18 18:37:27

标签: c++ c++11 vector

我有三个结构(Foo,Bar,Fruit),我想要一个向量来保存每个结构,如vector<Foo> Foo_holder; vector<Bar> Bar_holder; vector<Fruit> Fruit holder;,然后我想尝试将所有这三个向量放入一个向量中。所以它应该像这样结束,Vector_holder是我希望知道如何创建的顶级向量:

Vector_holder

--- Foo_Holder
------Instance of Foo

--- Bar_holder
------Instance of Bar

--- Fruit_holder
------Instance of Fruit

我该怎么做?

可能重复的问题列出了一个问题,即向量必须是相同的大小或代码中断,并且我的问题中的向量将大量移动大小。我也觉得这对初学者C ++学习者比其他问题更有帮助。 我在这里找到的解决方案对我有用,总体上比近篇文章的长答案简单得多。我更喜欢C ++的初学者,因此在这里更容易理解答案。

3 个答案:

答案 0 :(得分:7)

每当这样的分组有意义时,我倾向于将其放入struct并因此命名。在这种情况下,

struct FooBarFruitHolder {
    std::vector<Foo> foos;
    std::vector<Bar> bars;
    std::vector<Fruit> fruits;
};

然后您可以将其用作

std::vector<FooBarFruitHolder> vec;

vec.emplace_back();

和用对象填充它:

/* Add a Foo element to all FooBarFruitHolder instances. */
for (auto&& fooBarFruitHolder : vec)
    fooBarFruitHolder.foos.emplace_back(/* Arguments passed to Foo ctor */);

命名在这里至关重要,因此请选择适合您应用的最佳选择。将此嵌套数据结构的一部分传递给设置成员变量的函数时,初始化也可能更容易阅读,例如

void initialize(std::vector<Foo>& foos)
{
    foos.emplace_back(/* Arguments for first Foo object */);
    foos.emplace_back(/* Arguments for second Foo object */);
}

initialize(vec.front().foos);

答案 1 :(得分:0)

  

vector用于保存每个结构,如vector Foo_holder;向量   Bar_holder;矢量水果架;然后我想尝试并把它   所有这三个向量都变成一个向量。

解释你的(有点模棱两可的)语句的一种方法是你还需要一个包含所有N个元素类型的向量。 (但我怀疑你会更喜欢lubgr的答案。)

对于第三个载体,我建议你考虑多态性。

如果从接口类派生每个结构,也许

class FooBarFruit_t 
{
    //...
    virtual void whistle() = 0;
    virtual void bounce()  = 0;
    virtual void f1()      = 0;
    virtual void f2()      = 0;
    virtual void f3()      = 0;
    virtual void reflect();

    //...
}

然后您可以轻松创建一个向量,其中可以加载任何N种类型

std::vector<FooBarFruit_t*> holder;  

下一个挑战是创建每个派生类都可以支持的虚方法。

a)它们可能是抽象的,f1(),f2()......

b)它们可能非常具体,例如whistle(),这是foo只能做的事情(酒吧和水果不会被命令吹口哨())。

[我不确定这些典型的动画实例可能会采取什么样的行为,但软件是抽象真正有用的地方。]

这给你买的是,在运行时,你不必知道你指挥什么样的FooBarFruit_t。

通过调用f3(),每个实例(foo或bar或fruit)都会按照你的要求执行,每个f3()只是满足你对该类型的期望。

如果实例没有反射(),你可以实现a)什么都不做的方法,或者b)调用FooBarFruit_t :: reflect()。或其他几个选项。

考虑您可能想要显示所有对象:

 for (auto fbf : holder)  fbf->show();

 for (auto fbf : holder)  fbf->diagnostic();  // or diagnostic

 for (auto fbf : holder)  fbf->reset();       // or reset

任何理由都需要被视为不同?

应该是您认为需要根据类型执行某些操作的地方:

 void something() {
 for (auto fbf : holder) {

    switch(fbf.type())
    { // vvvvv - enumeration of types
       case   Foo: foosomething(); break;
       case Fruit: fruitsomething(); break;
       case   Bar: barsomething(); break;
       default : assert(0); break;
    }
 }
 }

但没有人会阻止你这样做,你认为你必须这样做。

答案 2 :(得分:0)

您可以使用Boost的zip迭代器将不同的矢量“压缩”在一起:

vector<Foo> Foo_holder; 
vector<Bar> Bar_holder; 
vector<Fruit> Fruit holder; 

/* ... insert elements etc. */

auto start = boost::make_zip_iterator(
    std::make_tuple(ia.begin(), d.begin(), ib.begin())
    );
auto end = boost::make_zip_iterator(
    std::make_tuple(ia.end(), d.end(), ib.end())
    );

现在,这不会产生向量,只会产生一对迭代器。但现在您可以将它们与STL算法一起使用。例如:

std::for_each(start, end, [](auto a_foo, auto a_bar, auto a_fruit) {
    std::cout << "The Foo   element is " << foo << "\n";
    std::cout << "The Bar   element is " << bar << "\n";
    std::cout << "The Fruit element is " << fruit << "\n";
}

您还可以使用这些迭代器来创建单个范围对象。例如,@ this answer通过@leemes对我的相关问题进行了描述。