AlastairG
AlastairG

Reputation: 4314

How can I prevent users deleting the pointer of a container member?

I have an API that returns a constant list of objects which represent non-copyable operating system resources. I want the list to be an absolute source of truth as to the state of the resources. If an application took a copy and manipulated the copy then the corresponding state change of the resource would not be reflected in the object stored in the list, so I want to prevent this, and also prevent removing resources from the list.

I have deleted various constructors and assignment operators and am so far happy that the user can only reference list members, and the list is itself a reference and I have satisfied myself that the list itself cannot be copied. I am also happy that pop_back() and similar calls fail because the list is returned as const.

However, this code compiles and potentially breaks the list.

const std::vector<MyClass> &list = MyClass::GetList();
const MyClass              *test = &(list[0]);

delete test;

I know that you would have to be a muppet to do something like this, but in my 25 year career I have seen many such muppets earning good salaries (I suppose) as professional software engineers.

I'm pretty sure that this would cause a crash of some sort, or some other undefined and potentially application breaking behaviour that will, hopefully, be caught before the code goes into production. Hopefully. Hahahaha.

How can I make this code generate a compile error or otherwise smack said muppets over the back of the head with their own stupidity?

Upvotes: 2

Views: 96

Answers (1)

AlastairG
AlastairG

Reputation: 4314

Thanks to HolyBlackCat for the spark of inspiration.

The answer is...extend the pimpl idiom...which I was already using.

In the implementation of MyClass have a static map of the available resources. Make it so MyClass only contains the key of its entry in said map. The implementation of the functions in the MyClass interface all look up the actual instance of the resource in the map and then call the equivalent API on that instance.

The list no longer needs to be protected at all. The lookup ID is private and read only. Callers can do whatever they wish with the list and the list members without damaging the underlying data at all.

Upvotes: 1

Related Questions