One way to achieve this is with a key class that wraps a numeric identifier and that cannot be directly created, so links are forced to be accessed using a variable of the type:
Using the code above, the key definition will look like this:
// some_registration.h DECLARE_KEY(Value); DECLARE_KEY(AnotherValue); // ... // some_registration.cpp DEFINE_KEY(Value, 1); DEFINE_KEY(AnotherValue, 2); // ...
It is important to note that the registration code above can now be divided into several separate files, so you do not need to recompile all the definitions at once. For example, you can split the registration into logical groups, and if you add a new record, you will need to recompile only one subset, and only code that really depends on the corresponding * .h file should be recompiled (another code that does not refer to this specific key value, no longer need to be updated).
Usage will be very similar to the previous one:
GetValueFromDatabase(Value); AddValueToDatabase(Value, 5); int* temp = new int[keys::count()];
The corresponding key.cpp file for doing this will look like this:
namespace keys { namespace { class KeyImpl : public Key { public: KeyImpl(const string& name, size_t id) : id_(id), name_(name) {} ~KeyImpl() {} virtual size_t id() const { return id_; } virtual const std::string& name() const { return name_; } private: const size_t id_; const std::string name_; }; class KeyList { public: KeyList() {} ~KeyList() {
As noted in the comments below, one of the drawbacks of the approach that allows decentralization of registration is that it then becomes possible to get into conflict scenarios where the same value is used several times (the above example adds an error for this, but this happens in runtime, when it would be very nice to handle such a thing at compile time). Some ways to mitigate this include commits that run tests that check for such a condition or policy, such as choosing an identifier value that reduces the likelihood of reusing an identifier, such as a file that indicates the next available identifier that needs to be enlarged and sent as a way to extract identifiers . Alternatively, assuming you are allowed to shuffle identifiers (I suggested that in this solution you should keep the current identifiers that you already have), you can change the approach so that the numerical identifier is automatically generated from the name (for example, by accepting hash of the name) and, possibly, use other factors, such as __FILE__, to deal with collisions, so that the identifiers are unique.