Assume I have a container type to which I would like to attach additional information. My approach would be to define a class holding the container and the info. Is it good practice to define methods for the new class which mimic the container's methods? E.g., instead of writing myContainerObject.internalVector[i]
I would like to write myContainerObject[i]
. One would have to redefine every method one wishes to use (size(), push_back()
etc.). What are the drawbacks of such an approach? What alternatives exist (e.g., is inheriting from a container the better solution?).

- 593
- 6
- 11
-
Related: http://stackoverflow.com/questions/6806173/subclass-inherit-standard-containers – jrok Jul 24 '13 at 08:11
3 Answers
You are using composition with forwarding functions, and it's the right thing to do with concrete classes like STL containers. One drawback is that you have to redefine every overload of every function you want to allow, only to forward arguments, as well as parrot-typedef nested types (like iterator
).
An alternative is to inherit but never publicly, only with private inheritance (because STL containers' destructor is public and non-virtual), then use using-declarations inside the custom class to bring names of base-class functions and types into scope (needing only one using Base::name;
for all overloads of a function).

- 4,690
- 24
- 31
-
1If you only want to forward, there's no need to implement all overloads. A template function will probably do most of the time. If OP can use C++11 and hence variadic templates, there shouldn't be any problem with varying numbers of arguments. – arne Jul 24 '13 at 08:17
-
@arne Not wrong, but consider for example `reference operator[](size_type pos);` and `const_reference operator[](size_type pos) const;`, how would you templatize that? Also for typing repetition, compare `typedef typename std::vector
::iterator iterator;` vs `using typename std::vector – gx_ Jul 24 '13 at 08:41::iterator;` -
I'm not sure about the rules now, but I think you'd only need to provide two overloads for the first problem: one `const` with `const_reference` as the return type and one non-const. Your second point, however, is totally valid. But as OP mentioned, it's not necessary to fully implement the underlying class' interface. I'd only implement the parts I actually need. – arne Jul 24 '13 at 08:45
-
@arne Yes, that's actually what I said (well, I think). Anyway +1 for mentioning (variadic) templates which indeed will do "most of the time" :) – gx_ Jul 24 '13 at 09:07
Possible ways of grasping a type which is a container, that I can think of:
Provide the a decorator (this is what you are asking about) whose component will be the internal container. This is can work when you have strict interfaces which you must comply with. It's neither good or bad practice. Read about decorator design pattern.
Use an iterator concept in your algorithms instead of a container. This a generic approach, and how stl algorithms are implemented
Use a container concept - similar to (2). Detect if the type is a container (SFINAE trick) and manipulate it.
Reimplement the container interface. You need a really strong reason to do it since it requires a significant amount of work/know-how. Some info: http://stdcxx.apache.org/doc/stdlibug/16-3.html
Generally , unless your uses case is very, very trivial or you have some specific requirements you should not expose class internal state (myContainerObject.internalVector[i]) to out side world.

- 897
- 1
- 7
- 19
Best practice is to keep the internals private and implement the [] operator
and other functions (size()
and such).

- 30
- 5