2

Where I work we have our own system library, which pretty much is only wrappers around the STL, such as:

template <typename T>
class HVector {
protected:
    std::vector<T> data;
public:
    int size () const; //Only returns data.size()
    int custom(); //Some generic custom function that uses the data vector
}

Most of the class members are just re-declarations of the STL container members, but we also have a few customized functions that do some generic tasks with the container.

Is this a good design? If not, what would be the best way to implement the customized functions around the containers?

  • 1
    was it always just wrappers around STL though? it may predate the STL and has later been reimplemented using the STL – jk. Apr 9 '14 at 14:55
  • Yes, it was designed to be like wrappers such as the Qt library. – Pedro Tabacof Apr 9 '14 at 18:38
  • Qt isn't a wrapper library. It's it's own library of containers, widgets, etc. – Michael Kohne Apr 10 '14 at 11:55
  • Generally, it is a bad idea. If you want some extra functions, you should write free functions as it is done in STL. And if you write a "wrapper", you should hide the container and provide function adapted to your specific usage. – Phil1970 May 12 '17 at 17:19
6

It depends on the nature of those custom operations, but probably yes, it's bad design. And the main reason for stating this is that you are coupling operation and storage.

If a certain custom operation is semantically independent, it can be better implemented as an standalone (functor) class or function, taking an specific container parameter. Moreover, if it doesn't depend on the concrete container class, it can be added an extra template parameter specifying it, or even better, refactored in order to work over iterator ranges. See, just like the STL algorithm functions.

Also, wrapping the way you do it involves forwarding a significant part of the wrapped container's public interface. This is a clear smell.

  • 2
    I disagree that there's anything smelly about it. Wrapping the way the OP does creates a project-wide interface that makes it easier to replace the underlying implementation with something else should the need arise. I've had that need arise enough times that I wrap everything that makes sense. – Blrfl Apr 9 '14 at 15:27
  • I hope your wrappers don't break inlining. – Benjamin Bannier Apr 10 '14 at 15:22
  • @Blrfl It's a lot harder to argue that someone will need to replace the Standard library than some third-party lib, though... How likely is that in reality? I really doubt that the burden of writing and maintaining wrappers, and every other reader not recognising what they're seeing or understanding why it's there, could possibly justify wrapping the stdlib. – underscore_d Sep 23 '18 at 16:16
  • @underscore_d Everything in moderation. What makes it into std has usually had time to become fully-baked and is unlikely to be replaced with something else. Since I was writing threaded programs long before C++11, wrappers made sense and paid off when I found a better implementation that the one I was using. I'd imagine that if some of that old code is still being maintained, someone will have made it wrap std::thread by now but wouldn't have unwrapped it since that was the known standard used throughout the project(s). – Blrfl Sep 23 '18 at 17:50
1

I wouldn't, I'd rather see a class that is a vector if its basically just a vector with 1 or 2 custom functions.

For these custom functions, I'd say its better to make functions that operator on the type, for example all the methods in . You might find this approach is a little more generic and so encourages reuse across your wrapper classes.

However, if the class is more than a vector, and just happens to use a vector as internal data storage, then that's fine. A Customers class that deals with a vector of Customer objects is one thing. Re-implementing a vector with your own vector isn't.

0

I've preferred to derive from the STL to add functionality and also hide the templating. So rather than use the vector as a member variable, I would derive so that my CustomVector is still a vector, and all the methods that are available on a vector, are also available on my CustomVector. Also, any method that can work off a Vector will also work on my custom class.

If you wanted to keep the exposure of the templates, as you do in your example, it's easy enough to do with this technique.

  • 3
    Isn't it a bad practice to inherit STL containers due to the fact that they don't provide virtual destructors? – Pedro Tabacof Apr 9 '14 at 18:38
  • Only if you add additional data members. Extending an stl container by simply wrapping it or adding extra member functions should be fine, as there's nothing new to destroy. – bstamour Apr 9 '14 at 19:24
  • Pedro: It's bad practice if it's possible for users to delete your derived instances through a pointer to base. If that's not a possible feature of your design, I don't see how it matters. However, there are likely other reasons not to derive from stdlib containers. @bstamour Sadly, saying "should" doesn't mean "is". If it's possible to delete the derived instance through a pointer to one of its bases - & some caller does that, & the base did not have a virtual destructor, then the behaviour is undefined, regardless of whether or not you see any reason that it should or shouldn't work. – underscore_d Sep 23 '18 at 16:21
0

Your wrapper may have some logic inside to deal with the template. And basically all STLs are templates by themselves.

This doesn't shock me. Imagine you want to have an array of objects "Cars" and other of objects "Bicycles". Same structure but different data manipulation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.