【问题标题】:C++ Generic VectorC++ 通用向量
【发布时间】:2013-05-23 17:24:43
【问题描述】:

是否可以在 C++ 中创建多种类型的向量?我希望能够构建和迭代包含许多不同类型的向量。例如:

vector<generic> myVec;
myVec.push_back(myInt);
myVec.push_back(myString);
etc...

向量需要能够容纳不同的数据类型。我应该在 c++ 库中使用另一种类似矢量的类型吗?

感谢任何方向。

【问题讨论】:

  • 可能是boost::variant 的向量。
  • 另一个选择是boost::any
  • 不是 std::vector 而是 std::tuple(在 C++11 中)。 std::vector 是统一类型的容器。
  • @AdityaKumar:但这固定了每个元素的大小和类型,这比多态对象的向量限制得多。
  • 在使用boost::any 之前,我会仔细查看您的代码,看看是否还有其他更好的方法。因为有。

标签: c++ generics vector


【解决方案1】:

您可以使用boost::any。例如:

#include <vector>
#include <boost/any.hpp>
#include <iostream>

struct my_class { my_class(int i) : x{i} { } int x; };

int main()
{
    std::vector<boost::any> v;

    v.push_back(42);
    v.push_back(std::string{"Hello!"});
    v.push_back(my_class{1729});

    my_class obj = boost::any_cast<my_class>(v[2]);
    std::cout << obj.x;
}

如果您想将允许的类型集限制在某个定义的范围内,您可以改用boost::variant

#include <vector>
#include <boost/variant.hpp>
#include <iostream>

struct my_class { my_class(int i) : x{i} { } int x; };

int main()
{
    typedef boost::variant<int, std::string, my_class> my_variant;
    std::vector<my_variant> v;

    v.push_back(42);
    v.push_back("Hello!");
    v.push_back(my_class{1729});

    my_class obj = boost::get<my_class>(v[2]);
    std::cout << obj.x;
}

boost::variant也支持访问。您可以定义一个可以处理变体中所有可能类型的访问者:

struct my_visitor : boost::static_visitor<void>
{
    void operator () (int i)
    {
        std::cout << "Look, I got an int! " << i << std::endl;
    }

    void operator () (std::string const& s)
    {
        std::cout << "Look, I got an string! " << s << std::endl;
    }

    void operator () (my_class const& obj)
    {
        std::cout << "Look, I got a UDT! And inside it a " << obj.x << std::endl;
    }
};

然后像下面这样调用它:

int main()
{
    typedef boost::variant<int, std::string, my_class> my_variant;
    std::vector<my_variant> v;

    v.push_back(42);
    v.push_back("Hello!");
    v.push_back(my_class{1729});

    my_visitor mv;
    for (auto const& e : v)
    {
        e.apply_visitor(mv);
    }
}

这是live exampleboost::variant 的好处是它将执行编译时检查以确保您的访问者可以处理变体可以包含的所有类型。

【讨论】:

  • @ChristopherBales:很高兴我能帮上忙 :)
  • 不幸的是,boost::any 似乎没有获得价值的好方法,除非您对其进行 any_cast。
  • 您需要为每种类型执行此操作for (vector&lt;boost::any&gt;::iterator it = test.begin(); it != test.end(); it++) { if (strcmp(it-&gt;type().name(),"i")==0) { cout &lt;&lt; boost::any_cast&lt;int&gt;(*it) &lt;&lt; endl; } else if (strcmp(it-&gt;type().name(),"Ss")==0) { cout &lt;&lt; boost::any_cast&lt;string&gt;(*it) &lt;&lt; endl; } }
  • @ChristopherBales:除了any_cast 之外,你可能会对未知类型的对象做什么?对于此评论中的代码,正确的做法是使用boost::variant 并应用此答案中描述的访问者模式。
  • @MooingDuck 我已经习惯了 C#,您可以在其中创建 IEnumerable 添加整数(对象)、字符串,以及任何您想要的对象。然后,您可以轻松地遍历集合。由于转换问题,这显然是 C++ 中更复杂的问题。 -- 例如 my_visitor 类必须确保它涵盖所有可能的类型,因此不是很通用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多