【问题标题】:How can I create a vector that holds three different types of vectors如何创建一个包含三种不同类型向量的向量
【发布时间】:2018-11-27 15:51:01
【问题描述】:

我有三个结构(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++ 的初学者,因此很欣赏这里更容易理解的答案。

【问题讨论】:

  • 你的意思是std::tuple
  • 问题无法按要求解决。有多种技术可能适合 OP,但为了提出这些建议,我需要更多关于实际所需行为的信息。
  • 为什么不用std::tuple来存储三种不同类型的向量呢?
  • 我没有考虑元组。我应该阅读它们,谢谢!
  • 所以我会做std::tuple<Foo_holder,Bar_holder,Fruit_holder> Vector_holder;?

标签: c++ c++11 vector


【解决方案1】:

每当这样的分组有意义时,我倾向于将其放入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);

【讨论】:

  • 在我的情况下,这实际上似乎是一个非常好的主意。我会试试看效果如何。
  • 如何访问向量 foos 并查看/添加 Foo 实例?
  • FooBarFruitHolder.foos.push_back()@MaxBethke
  • 试试看吧:) @MaxBethke
  • @Sailanarmo 很抱歉问了这么多问题,但你为什么在vec.emplace_back(); 没有任何东西可以安置回来?
【解决方案2】:

vector 用来保存每个结构体,例如vector Foo_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 可以做的事情(并且 bar 和 fruit 在被命令到 whistle() 时不会采取任何行动)。

[我不确定这些通常没有动画的实例会采取什么样的行为,但软件是抽象真正有帮助的地方。]


这为您带来的是,在运行时,您不必知道您正在命令采取何种 FooBarFruit_t。

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

如果实例没有reflect(),您可以实现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;
    }
 }
 }

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

【讨论】:

    【解决方案3】:

    您可以使用 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";
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-15
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多