I've asked this on a couple of other forums and got some useful responses but I'm still not 100% sure as to the best way to proceed with this. I've got this problem of representing a "weird" kind of graph structure, which is like a normal graph but it has an additional layer of structure called "strings" which are composed of nodes connected together and ordered in a linear order. The purpose of this graph is to represent a system of levels in a game. In one of the responses I got, it was suggested I should implement this using a conventional graph type (i.e. just an implementation of a conventional graph, like Boost's graphs). But the problems appear when considering the "strings". Namely, I have something like this:
class WeirdGraph {
private:
class NodeString {
private:
<...>
std::vector<WeirdGraphNodeIterator> nodes;
<...>
public:
<...>
};
<... (there is a graph variable declared here) ...>
std::vector<NodeString *> strings;
<...>
public:
<...>
};
i.e. the weird graph object contains a private class to represent the strings. Problems are that: 1. iterators in the graph get invalidated. Each node string stores the nodes comprising it as iterators into the graph. When a node is deleted, the iterators get invalidated, and this seems to require an update to the NodeStrings. What can be done? Obviously, one could just use a graph that does not invalidate iterators (though this may lead to a penalty accessing/traversing the graph, hence why I'm a little hesitant, since I'm going to be accessing more than I'm going to be deleting stuff, though I doubt this is used in performance-critical code in any case so it probably doesn't matter.). But I'm curious to know if there may be a technique that would work even in the case of invalidating iterators. 2. To update, the node strings need to know what nodes belong to them. So the nodes contain a string ID field, which is user-specified when the user creates a string and the WeirdGraph enforces uniqueness. Is it "good form in C++" to have WeirdGraph do the enforcing and not NodeString? It feels iffy. 3. Regarding that, is there an alternative to using the user-specified string IDs that won't fail (e.g. incrementing a counter may fail long off into the future, but I doubt one will be creating and deleting billions of times. But is having that "latent failure" possibility in there OK? As it feels iffy too.)? 4. NodeString constructs nodes in its constructor, then deletes them in the destructor. This last bit makes me feel iffy as then it's not okay to pass one by value -- though we can always not do that, but I'm not sure whether having such requirements which are enforced only by user understanding is a good idea (although does it matter here since NodeString is a private internal of WeirdGraph?).
Any comments on these issues? Right now I'm really leaning toward using a non-invalidating graph type, as that would entirely eliminate 3 out of the 4 issues above, but I'd still like to know what the deal is on the 4th. The 4th is also why I'm using pointers above (perhaps I should use std::auto_ptr instead of raw pointers there? hmm) instead of objects directly, since that would necessitate some copying/by-value passing when filling that vector.