Have you considered why you have named your class/struct Texture
? The keywords are meaning, concept, intention...
Consider your struct Texture
design to be a razorblade, it cuts extremely well (no compilation overhead, no initialization overhead, you have full control). If you are going to be "juggling" a lot of those, you increase the risk of hurting yourself (by null pointer exceptions or garbage values from uninitialized members, among other things). The Texture
structure has a bug generation risk factor of, say, 0.05% of the time. It is also not that self-explanatory, so it is a deceptively good-looking razor. When you see it, you don't realize how dangerous it may be if you are going to handle it. The more you play with it, chances you will get cut rise very quickly. Finally, you don't really understand very quickly what its potential usefulness might be to you.
The class Texture
design also cuts (to the heart of the problem, no less), and it cuts well. This is more like a kitchen knife, with a handle. It has a bug generation risk factor that is much smaller, say 0.001% of the time, because now, you are your only problem, the class users will only touch the knife from its handle (its public API, your declared public methods/members only), while you are free to sharpen the blade (its private members) in all secrecy, behind the scenes. Furthermore, through its methods, its intended meaning/functionality is clearer, so it is a shiny silver kitchen knife, you know one when you see it (knife blades are almost always silver, like most image textures are made of pixels, though this is also a different matter of discussion). You can play with it much longer before any serious bug may come up.
In short, your solution is over-engineered when you are not going to exploit the designed capabilities to the maximum possible extent. You will have to get the feeling with time, how to choose the right tools for the job, but, more often than not, it depends on the job. And that's why we don't use scalpels to slice bread, and surgeons don't use kitchen knives to perform surgery.
By the way
it's hard for me to decide whether or not I should keep it simple as
in the second case, or write "proper" code as in the first case.
Your second case is not simple, it is excessively simple. There is a threshold while travelling down the complexity ladder, beyond which a design becomes bad. Keeping it simple was never meant to include dropping fundamentals, a good constructor of an object certainly being one.
std::vector<Color> const& image_data()
struct Texture
is a semiregular type, butclass Texture
is only copyable You'll have trouble with, e.g.std::array<class Texture, 10>
buf_.size() == (w_ * h_)