Search code examples
c++uniqueidentifier

How to manage file unique IDs in c++


c++ (not c++11)

Say i have 100 .cpp files in my project, which currently do some work. All of those files currently include some globals.h file which i can edit easily.

I want each of those files to have its own instance of some object, and I also want that instance to have some unique ID of the file in which it is instantiated. In addition, I want those objects to be created by a factory method, and I need the instances to have some way for a user to handle them - meaning they can't be anonymous.

In short - I need a way to generate unique IDs for all of the files in my project, i need the file to be able to access its own ID using the same name in all files, but also to be able to access the ID of a file externally in another "manager" file.

Here are options that don't work:

1. Enum:

If I use an enum and give every file an enum ID, now I can't do this in globals.h:

static thePrivateInstanceInThisFile = theFactory.makeInstance(fileID);

because I need a different fileID in every file, and that was defined statically, and uniquely named using my enum.

2. Class that counts its own instances

Define in globals.h:

class FileIDGiver{
private:
   static int currentID;//initialize to 0 in cpp
   int myID;
public:
   FileIDGiver(){
      myID = currentID++;
   }
   int getFileID(){
       return myID;
   }
}

static FileIDGiver theFileId;

static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());

This will give an ID to each static file instace which is unique to the file, but now it is not manageable externally to the file.

I thought about doing something like

globals.cpp
int file1ID;
int file2ID;
...

globals.h
extern file1ID;
extern file2ID;
...

file1.cpp
file1ID = theFileId.getFileID();

file2.cpp
file2ID = theFileId.getFileID();

...

and whenever a user needs to manage a file he would either use the file's ID variable, or create a new one in the above manner.

This would allow me to access each uniquely and automatically file ID externally. The only problem I have with this is the line file1ID = theFileId.getFileID(); only executes in runtime, AFTER the line static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());. which executes at compile time.

I can't figure out a good way to reverse this order, or maybe do a whole other mechanic.

Again - I need:

  1. Automatically created file IDs

  2. Unique file IDs (which are very very preferably numbers)

  3. Usage of those IDs by the same variable name in all files (automatically, using a static variable definition in the globals.h file)

  4. Ability to access a specific file ID manually by using another manually defined variable.

Please advise some good way to accomplish this

Thanks.


Solution

  • If you want to be able to access the static Instances of other files, then this cannot be done via an automatically generated id because the id generated for a file could change each time a new file is added, or every time it is compiled, or even on each execution. Therefore in this solution, each file manually defines its own persistent id similarly to example 1 in the question.


    ids.h

    enum FileId
    {
        File1, File2, File3
    };
    

    factory.h

    #include "ids.h"
    #include "instance.h"
    
    class Factory
    {
        // ...
    public:
        Factory() {/*...*/}
        Instance createInstance(FileId fileid) {/*...*/}
    };
    
    Factory &getTheFactory();
    

    factory.cpp

    #include "factory.h"
    
    Factory &getTheFactory()
    {
        static Factory theFactory;
        return theFactory;
    }
    

    idmanager.h

    #include "ids.h"
    #include "instance.h"
    
    template<FileId id>
    struct Manager
    {
        static Instance &getInstance(); // not defined
    };
    

    global.h

    #include "idmanager.h"
    #include "factory.h"
    
    template <>
    Instance &Manager<FILEID>::getInstance()
    {
        static Instance theInstance = getTheFactory().getInstance(FILEID);
        return theInstance;
    };
    
    static Instance &getThisFileInstance()
    {
        return Manager<FILEID>::getInstance();
    }
    

    Usage is as follows: for each file requiring a static Instance object, place at the start

    #define FILEID File1   // The FileId corresponding to this file
    #include "global.h"
    

    Then in any file,

    • The unique id is given by FILEID. (sorry it's a macro)
    • The static Instance of this file is obtained by getThisFileInstance().
    • The static Instance of any file is obtained by Manager<any_file_id>::getInstance().

    This works by placing the implementation for an instantiation of the template Manager<FileId> in each file, each of which creates and returns that file's static Instance.

    Advantages are persistence of ids, and zero run-time overhead: no need to dynamically assign ids, and the calls to Manager<file_id>::getInstance() are resolved at compile-time.

    Also, the ids.h header can easily be generated by a script which scans the first line of each file for #define FILEID fileid, so the only maintenance left is remembering to write #define FILEID fileid.