Merge branch 'main' of feistymeow.org:feisty_meow
[feisty_meow.git] / structures / unique_id.h
1 #ifndef UNIQUE_ID_CLASS
2 #define UNIQUE_ID_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : unique_id                                                         *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1999-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include <basis/contracts.h>
19
20 namespace structures {
21
22 //! Provides an abstraction for the responsibilities of a unique identifier.
23 /*!
24   These are generally used as a way of masking the underlying ID object while
25   providing some equality comparisons.  It is especially useful when the
26   underlying object is not itself an object, but just a simple type.
27 */
28
29 template <class uniquifier>
30 class unique_id : public virtual basis::equalizable
31 {
32 public:
33   unique_id(uniquifier initial_value) : _id(initial_value) {}
34     //!< Constructs a unique id from the "initial_value".
35
36   unique_id(const unique_id<uniquifier> &to_copy) { *this = to_copy; }
37     //!< Constructs a unique id as a copy of the "to_copy" object.
38
39   ~unique_id() {}
40
41   virtual bool equal_to(const equalizable &to_compare) const {
42     const unique_id<uniquifier> *cast = dynamic_cast<const unique_id<uniquifier> *>(&to_compare);
43     if (!cast) throw "error: unique_id::==: unknown type";
44     return cast->_id == _id; 
45   }
46
47   //! Returns true if the held id is the same as "to_compare".
48   /*! The templated uniquifying type absolutely must provide an equality
49   operator (==) and an assignment operator (=). */
50   bool operator == (const unique_id<uniquifier> &to_compare) const
51           { return _id == to_compare._id; }
52
53   //! Sets this id to be the same as "to_copy".
54   unique_id & operator = (const unique_id<uniquifier> &to_copy)
55           { if (this != &to_copy) _id = to_copy._id; return *this; }
56
57   uniquifier raw_id() const { return _id; }
58     //!< Returns the held identifier in its native form.
59
60   void set_raw_id(uniquifier new_value) { _id = new_value; }
61     //!< Sets the held identifier to "new_value".
62
63 private:
64   uniquifier _id;  //!< the held object in its native form.
65 };
66
67 //////////////
68
69 //! A unique identifier class that supports sorting.
70 /*!
71   The orderable version can be compared for magnitude and permits sorting
72   the ids based on the underlying type.  The underlying type must implement
73   at least the less than operator.
74 */
75
76 template <class uniquifier>
77 class orderable_unique_id : public unique_id<uniquifier>
78 {
79 public:
80   orderable_unique_id(const uniquifier &initial_value)
81           : unique_id<uniquifier>(initial_value) {}
82   orderable_unique_id(const unique_id<uniquifier> &initial_value)
83           : unique_id<uniquifier>(initial_value) {}
84   ~orderable_unique_id() {}
85
86   /*! the "uniquifier" type absolutely must provide a less than operator (<)
87   and it must meet the requirements of the "unique_id" template. */
88   bool operator < (const unique_id<uniquifier> &to_compare) const
89           { return this->raw_id() < to_compare.raw_id(); }
90 };
91
92 //////////////
93
94 //! A unique identifier based on integers.
95
96 class unique_int : public unique_id<int>
97 {
98 public:
99   unique_int(int initial = 0) : unique_id<int>(initial) {}
100     //!< implicit default for "initial" of zero indicates bogus id.
101
102   bool operator ! () const { return raw_id() == 0; }
103     //!< provides a way to test whether an id is valid.
104     /*!< This uses the implicit assumption that a zero id is invalid or
105     unassigned. */
106 };
107
108 } //namespace.
109
110 #endif
111