I’m wondering if the following use of typedefs is any good practice, or if there are any downsides to it.
Basically I have alot of “data”-structs, which are intended to be used in (globally unique) containers, and they hold indices to other (globally unique) containers, the reason is to keep memory access localized. Rather than having the indice types be generic size_t I thought of naming them as follows for clarity:
typdef uint32_t MeshID;
typedef Mat4 Transform;
typedef std::vector<Transform>::size_type TransformIndex;
struct AABB
{
AABB(const Vec3& center, const Vec3& extent);
typedef std::vector<ModelMesh>::size_type AABBIndex;
Vec3 mAABBCenter;
Vec3 mAABBExtent;
};
struct ModelMesh
{
ModelMesh(const MeshID meshID, const uint32_t aabbIndex, const uint32_t transformIndex);
typedef std::vector<ModelMesh>::size_type ModelMeshIndex;
const MeshID mMeshID;
const AABB::AABBIndex mAABBIndex;
const TransformIndex mTransformIndex;
};
struct ModelNode
{
ModelNode(const uint32_t aabbIndex, const uint32_t transformIndex);
typedef std::vector<ModelNode>::size_type ModelNodeIndex;
const ModelNodeIndex mNodeStartIndex;
const ModelNodeIndex mNodeEndIndex;
const ModelMesh::ModelMeshIndex mMeshStartIndex;
const ModelMesh::ModelMeshIndex mMeshEndIndex;
const AABB::AABBIndex mAABBIndex;
const TransformIndex mTransformIndex;
};
struct Model
{
Model(const std::string& name, const Mat4& initialTransform, const Vec3& minBounds, const Vec3& maxBounds, const MeshID meshID, MaterialPtr material);
Model(DX11Renderer& renderer, const JonsPackagePtr jonsPkg, const PackageModel& pkgModel, LoadMaterialFunc loadMaterialFunction);
~Model();
bool operator==(const Model& m);
bool operator==(const std::string& modelName);
const std::string mName;
const size_t mHashedID;
const ModelNode::ModelNodeIndex mRootNodeIndex;
};
The motivation is so that the relation between the structs are clear. The downside is perhaps alot of definitions? Too chatty?
Overall, is this good practice?
1
The heart of creating abstractions is to give things a good name, which makes clear what a specific data type represents. And that’s what you are doing here, no less, no more.
Creating the right abstractions is what makes actually the difference between good code and bad code, so yes, assumed these abstractions serve you well, that is good practice.
In general, using a typedef is never really a bad thing, all it does is tell the compiler that when you use, say “Transform,” you actually meant “Mat4.” All typedef does is make it easier for the programmer to specify between separate types. There is usually no downside to using typedef.
Overall, it is neither a good nor bad practice. Just make sure you can remember what each typedef stands for.