Identifiable stands for any Object that contains unique ID (which can be any UTF-8 literal and is stored in std::wstring).

If you are looking for an Object with name and not an ID (not unique string literal), check Nameable instead.

The uniqueness of that ID is always considered in the scope of some IdentifiableCollection only, and will be checked in constructor (Identifiable::Identifiable(scopeToExtended)).

When you create an new object of e.g. ModelStatic type with Engine3D::createModelStatic(ID...), its check the uniqueness of given ID in the scope of all Engine3D's objects.

Once given (upon calling the constructor of the class), ID cannot be changed.

Usage in own classes

For example, if we want to create custom Album class with photos that have unique names:

class Photo : public Identifiable{
Photo(std::wstring ID, IdentifiableScope * scopeToExtended) : Identifiable(ID, scopeToExtended);
class Album{
std::vector< Photo* > photos;
IdentifiableScope * photosIDsScope;
std::wstring name;
Album(std::wstring name) : name(name){
photosIDsScope = new IdentifiableScope(
InCaseOfError("Photo with ID: \"", "\"already exists in album \""+name+"\"!", 0)
for(auto &photo : photos){
delete photo;
delete photosIDsScope;
addPhoto(std::wstring photoName){
photos.push_back(new Photo(photoName, photosIDsScope));
Album album1("winter");
album1.addPhoto("my cat");
Album album2("summer");
album2.addPhoto("my cat"); //no errors (different scopes)
album2.addPhoto("my cat"); //will generate an error: 'Photo with ID: "my cat" already exists in album "Summer"!'

Note that scope was checked and extended in Photo's constructor - before new object was added to photos.