Flow 1.0.0
Flow project: Public API.
|
Each object of this class stores (at construction) and returns (on demand) a numeric ID unique from all other objects of the same class ever constructed, across all time from program start to end. More...
#include <uniq_id_holder.hpp>
Public Types | |
using | id_t = uint64_t |
Raw integer type to uniquely identify a thing. 64-bit width should make overflow extremely hard to reach. | |
Public Member Functions | |
Unique_id_holder () | |
Thread-safely construct an ID whose value is different from any other object of this class, past or future. | |
Unique_id_holder (const Unique_id_holder &) | |
This copy constructor is identical in behavior to Unique_id_holder(), the default ctor. More... | |
id_t | unique_id () const |
Raw unique ID identifying this object as well as any object of a derived type. More... | |
const Unique_id_holder & | operator= (const Unique_id_holder &) const |
This assignment operator is a const no-op. More... | |
Static Public Member Functions | |
static id_t | create_unique_id () |
Short-hand for Unique_id_holder().unique_id() ; useful when all you want is the unique integer itself. More... | |
Each object of this class stores (at construction) and returns (on demand) a numeric ID unique from all other objects of the same class ever constructed, across all time from program start to end.
To be clear, the uniqueness is not just for all existing objects at a given point in time (for which this
could simply be used instead) but across all time.
For obvious reasons, Unique_id_holder cannot have standard copy construction and assignment semantics. It was contemplated to simply make class noncopyable (forbidding copy construction). However, then no derived type could use auto-generated copy construction and/or operator=()
, making the deriving usage pattern (see below) considerably less concise for such types.
Therefore, it defines a (somewhat unusual) copy constructor: It is simply equal to the default constructor and simply generates a unique ID. The reason: a common pattern (see below) will involve type C
deriving from Unique_id_holder. If C
happens to use the auto-generated copy constructor implementation, Unique_id_holder's copy constructor will be invoked by this implementation. Since equal (by value) objects are still separate objects, the correct behavior is for the constructed object to gain a new ID.
The assignment operator operator=() similarly has unusual behavior: it does nothing, for similar reasons.
All operations safe for simultaneous execution on 2+ separate objects or on the same object. The ID accessor is a totally trivial accessor. Only construction requires any concurrent-access protection and internally uses an atomic
for good efficiency.
This can be used, in particular, to uniquely identify (over all time) objects of any type (across all types). The most concise usage pattern is probably via public (or possibly private) inheritance. Another is simply via composition (storage).
Update: A simplified pattern is now possible: If you just want the raw unique number itself and don't even want to keep Unique_id_holder objects around or refer to them, call the static create_unique_id() which returns a new raw id_t
integer. The above 2 usage patterns can be rewritten to pass around id_t
values. The "Example of outside code registering an object" sub-case is the one exception to that, as for that either store_in_table()
must continue to take a Unique_id_holder and not a raw integer, or I suppose m_uniq_id_holder
must be made public which some would not like.
|
explicit |
This copy constructor is identical in behavior to Unique_id_holder(), the default ctor.
Unique_id_holder doc header explains this behavior and why copy construction is not disallowed entirely.
|
static |
Short-hand for Unique_id_holder().unique_id()
; useful when all you want is the unique integer itself.
const Unique_id_holder & flow::util::Unique_id_holder::operator= | ( | const Unique_id_holder & | ) | const |
This assignment operator is a const
no-op.
Unique_id_holder doc header explains this behavior, and why assignment is not disallowed entirely.
*this
. Unique_id_holder::id_t flow::util::Unique_id_holder::unique_id | ( | ) | const |
Raw unique ID identifying this object as well as any object of a derived type.