我想制作一个包含不同类型向量的向量。假设我有4节课;狗,猫,猪,牛我想要一个包含每个向量的向量,并且能够通过两个索引访问它们,以便我可以对它们进行迭代,如果它是向量的向量就是这种情况。
我一直在玩类似的东西:
std::vector<std::variant<std::vector<Dog>,
std::vector<Cat>,
std::vector<Pig>,
std::vector<Cow>>>;
此外,我希望能够使用可变参数模板构造来构建这些数组,因此我可以轻松地制作另一个向量载体,例如Apple,Pear,Orange,Lemon,Lemon,Grape,Cherry。
我希望能够在我的代码中写一些东西:
MyVectorOfVectors<Dog,Cat,Pig,Cow> animals;
MyVectorOfVectors<Apple, Pear, Orange, Lemon, Grape, Cherry> fruits;
并为每种类型制作向量,并将这些向量存储在我可以通过索引访问的另一个向量(或类似向量)中。显然,该载体将需要是上述变体载体所建议的某种异构容器。我想这将必须包装在某种可变参数模板类定义中。
因此访问数组中的第三个Dog将需要类似这样的功能
Dog mydog = animals[0][3];
或者如果解决方案必须包装在一个类中,
Dog mydog = animals.thearray[0][3];
我意识到这可以使用类层次结构,动态分配和指向对象的指针来实现,但是我正在寻找一种具有平面内存模型的解决方案以提高性能。
答案 0 :(得分:3)
template<typename... T>
using MyVectorOfVectors = std::tuple<std::vector<T>...>;
MyVectorOfVectors<Dog,Cat,Pig,Cow> animals;
MyVectorOfVectors<Apple, Pear, Orange, Lemon, Grape, Cherry> fruits;
void foo()
{
std::vector<Dog>& dogs = std::get<0>(animals);
std::vector<Orange>& oranges = std::get<2>(fruits);
}
您必须决定:要么可以在编译时推断类型(在这种情况下,还必须在编译时知道您对MyVectorOfVectors
的索引)-然后,您将获得所有类型安全性(如上所述)。
如果索引也可以是运行时值,则需要一种类型的擦除类型。这将带有您要避免的运行时开销。
无论如何,您都不会得到Dog dog = animals[0][3]
,因为无论operator[]
最终是什么,MyVectorOfVectors
的参数在编译时不一定是已知的(从至少是编译器)。
答案 1 :(得分:1)
感谢您的建议。我使用Max Langhof的答案来生成数据结构,并找出了进行迭代的方法。
这是我最后得到的代码。
$("a[href='#button1']").click(function(e) {
$($(this).attr("href")).click();
});
如您所见,它与使用类型推断的非层次类一起使用,因此不需要我的Dog,Cat等从基类派生。
下一步是能够在lambda中使用参数,但至少我已经了解了这一点。
答案 2 :(得分:0)
我不确定这是您所需要的,对我来说这是一个奇怪的要求:
template<typename ...Ts>
using MatrixVariantRows = std::vector<std::variant<std::vector<Ts>...>>;
答案 3 :(得分:0)
根据您的要求,这是另一种可能性。需要权衡的是,从编译器的角度来看,您可以混合动物或水果(但不能混合动物和水果),但是该变体可确保在运行时无法访问错误的类型。
struct Dog {};
struct Cat {};
struct Pig {};
struct Cow {};
struct Apple {};
struct Pear {};
struct Orange {};
struct Lemon {};
struct Grape {};
struct Cherry {};
template<typename... Ts>
using MetaVector = std::vector<std::vector<std::variant<Ts...>>>;
int main(int argc, const char *argv[])
{
Dog daisy, sadie, molly;
Cat sam, coco, tiger;
Pig frankie, albert, digger;
MetaVector<Dog,Cat,Pig,Cow> animals = {{ daisy, sadie, molly },
{ sam, coco, tiger },
{ frankie, albert, digger }};
auto dog0 = std::get<Dog>(animals[0][0]);
auto dog1 = std::get<Dog>(animals[0][1]);
auto dog2 = std::get<Dog>(animals[0][2]);
auto cat0 = std::get<Cat>(animals[0][0]); // throws exception
MetaVector<Apple,Pear,Orange,Lemon,Grape,Cherry> fruits;
return 0;
}