And when you think about it screen changes are unlikely to happen while the program runs. Usually you set your screens up, before you start a program.
It doesn't matter as long as they
do happen. The library shouldn't just break down because we didn't consider this case.
So if a screen change event occurs you could simply set a flag and recompute the internal screen data at the next use.
How do you detect a change in configuration? How do you signal it to the user?
I think the data should be cached internally. It makes screens a lighter resource. [...] These are ideal conditions for caching. If you only hand out copys or references you also don't have problems with invalid pointers.
Yes, but either you return a copy of the whole vector (which is expensive and partially negates the caching advantage), or you return a reference (which brings back the problem of changing configuration during usage).
I'd personally weigh the performance argument less important than the validity one, so I tend to return a copy.
To keep a getByIndex() function would be helpful I think. I can think of cases where users want to get a screen from it's index (for example get the screen corresponding to a video mode), instead of copying the whole vector and the only pick one element.
I don't think this is necessary. If the user is really concerned about performance, he can store the vector himself.
Another reason why I wouldn't provide an index-based function is that it brings back the danger of outdated information: it's possible that the index which the user memorized refers to a meanwhile different screen.
There are two other things I'd like to discuss. First is I'd like to suggest a sf::Screen::contains(sf::Vector2) function. I can think of use cases where the user wants a window to go fullscreen on the monitor it's currently on. Right now there is no way to do it.
What about
screen.bounds.contains(vector)? What if the user wants the working area instead of bounds? It's too specific in my opinion.
In general, I don't like introducing specific functionality just for convenience reasons. As always in designing a new API, we should start with the minimal set of functionality, and extend it later based on user's needs. It's difficult to anticipate everything, and deprecating APIs because of wrong assumptions is much worse than introducing them a bit later.
There are really many parallels to the
sf::Joystick API. How do we handle joystick changes at runtime meaningfully? The more I think about it, the more it seems that we've made some design mistakes there. We should definitely reconsider this whole topic for SFML 3, also to unify the differently looking APIs.