假设我有不同类型的组件,它们是结构。也许我TransformComponent
有RigidBodyComponent
现在,这就是问题所在:我想要std::map
将组件类型和 id 映射到组件的位置。id 是将组件链接在一起的东西。我应该使用哪种容器?我不能使用,std::map<std::typeindex, std::map<id_t, T>>
因为类型T
取决于您用来索引第一个地图的类型索引。
您的用例听起来像是多态性的典型用法。您应该知道,任何将“非同质”类型存储在单个容器中的尝试都会带来多态性的性能损失。至于您是否会使用 C++ 提供的“开箱即用”多态性,还是使用自定义解决方案——这完全取决于您。
顺便说一句,引用问题评论中的一个问题:
假设你可以拥有这样一个容器。你会用它做什么?你能展示一些预期的用法示例吗?
这是一个非常好的问题,因为透露您的特定使用场景将允许其他人更详细地回答您的问题,因为现在听起来您并不真正知道自己在做什么或需要做什么。因此,如果您需要进一步的指导,您应该真正澄清并建立您的问题。
boost::any 或 boost::any_cast 怎么样?
如果您需要使用包含不同类型的容器,请查看一些 BOOST 库:
Any:用于不同值类型的单个值的安全通用容器。( http://www.boost.org/doc/libs/1_54_0/doc/html/any.html )
变体:安全、通用、基于堆栈的可区分联合容器 ( http://www.boost.org/doc/ libs/1_54_0/doc/html/variant.html )
如果您的类型列表定义明确且不会更改,请使用variant 。
所以你的代码看起来像这样:
typedef boost::variant<TransformComponent, RigidBodyComponent> my_struct;
std::map<std::typeindex, std::map<id_t, my_struct> > cont;
...
std::typeindex index = std::type_index(typeid(TransformComponent));
std::map<id_t, my_struct> & m = cont[index];
id_t id = ...;
TransformComponent & component = boost::get<TransformComponent>(m[id]);
这段代码很丑,所以考虑改变架构。使用 boost::any 或 boost::variant 可能会更简单。
PS 如果您编写模板代码,那么最好查看 boost::mpl。
因此,如果您不介意编写使用 ye olde C hacking 的自定义容器,您可以解决这个问题。
我在这里给你写了一个例子:
#include <iostream>
using namespace std;
struct ent
{
int myInt;
};
struct floats
{
float float1;
float float2;
};
struct container
{
bool isTypeFloats;
union
{
ent myEnt;
floats myFloats;
};
};
void main( void )
{
ent a = { 13 };
floats b = { 1.0f, 2.0f };
container c;
container d;
cout << b.float1 << " " << b.float2 << endl;
c.isTypeFloats = false;
c.myEnt = a;
d.isTypeFloats = true;
d.myFloats = b;
//correct accessor
if( c.isTypeFloats )
{
cout << c.myFloats.float1 << " " << c.myFloats.float2 << endl;
}
else
{
cout << c.myEnt.myInt << endl;
}
if( d.isTypeFloats )
{
cout << d.myFloats.float1 << " " << d.myFloats.float2 << endl;
}
else
{
cout << d.myEnt.myInt << endl;
}
}
要将这些结构放入容器中,您只需执行以下操作:std::vector< container >
你应该知道的几件事:
ent
,它也会为 a 分配空间,floats
所以每次存储一个ent
. 根据您的应用程序的用途和您存储的类型的大小,这可能可以忽略不计。void*
. 所以你会这样做:std::vector< void* > myVec
你会像这样插入:你的类型myVec.push_back( &x )
在哪里x
,例如ent
我们示例中的。但是读出来你必须知道你指的是什么,所以你必须知道做类似的事情:cout << ( ( ent* )myVec[0] )->myInt << endl;
因为你可能不知道它是什么类型,除非你有一些预定义的写作模式,你可能最终想要使用这样的容器结构:
struct container2 { bool isTypeFloats; 无效* myUnion;}