Wrapping linked lists in iterators

后端 未结 5 613
青春惊慌失措
青春惊慌失措 2021-01-20 01:21

A set of APIs that I commonly use follow a linked-list pattern:

struct SomeObject
{
    const char* some_value;
    const char* some_other_value;
    SomeObj         


        
5条回答
  •  有刺的猬
    2021-01-20 01:42

    1. You would make MyObjectIterator a friend of MyObject. I don't see any better way. And really I think it's reasonable that iterators get whatever special friend access is necessary for them to perform their duties.

    2. You don't seem to have considered how and where your MyObject instance are going to be stored. Or perhaps that's what this question is coming out of. It seems like you would have to have a separate linked list of MyObjects in your MyObjectList. Then at least MyObjectList::begin() can just grab the first MyObject of your internal linked list of them. And if the only operations that may modify or rearrange this list only ever happen through the iterators you provide, then you can problem keep these lists in synch without too much trouble. Otherwise, if there are functions in the API you're using that take the raw SomeObject linked list and manipulate it, then you may have trouble.

    I can see why you've tried to design this scheme, but having separate MyObjects that point to SomeObjects even through SomeObjects themselves make up the real list structure.... That is not an easy way to wrap a list.

    The simplest alternative is just to do away with MyObject completely. Let your iterators work against SomeObject instances directly and return those when dereferenced. Sure that does expose SomeObject to the outside, particularly its next member. But is that really a big enough problem to justify a more complex scheme to wrap it all up?

    Another way to deal with might be to have MyObject privately inherit from SomeObject. Then each SomeObject instance can be downcast as a reference to a MyObject instance and given to the outside world that way, thus hiding the implemtation details of SomeObject and only exposing the desired public member functions. The standard probably doesn't guarantee this will work, but in practice since they'll likely have the exact same memory layouts you may be able to get away with it. However, I'm not sure that I would actually ever try such a thing in a real program unless absolutely necessary.

    The last alternative I can think of is just to transfer the data into a list of more convenient data structures after being given to you by this API. And then of course transfer it back into a raw SomeObject list only if necessary to pass it back to the API. Just make your own SomeObjectData or whatever to store the strings and put them in a std::list. Whether or not this is actually feasible for you really depends on how this data is used in the context of the API you've mentioned. If there are other API functions that modify SomeObject lists and you need to use them frequently, then constantly converting SomeObject lists to and from std::list could be annoying.

提交回复
热议问题