4

I've created a new class that composes std::deque by private inheritance, i.e,

class B : private std::deque<A>
{ ... };

and in my source code I tried to use iterator of B, i.e.,

B::iterator it

The compiler error is

error C2247: 'std::deque<_Ty>::iterator' not accessible because 'B' uses 'private' to inherit from 'std::deque<_Ty>'

So the question is, how can I make the iterator accessible?

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
segfault
  • 5,759
  • 9
  • 45
  • 66
  • 4
    @TonyTheLion what you say does not apply to private inheritance, since one cannot bind a ``B`` polymorphically to an ``std::deque`` pointer or reference. – juanchopanza Sep 21 '12 at 15:33
  • @juanchopanza: agreed, although note that the class `B` can, if it's so stupid, so the author of `B` needs to take care. Users of class B can't, at least not without unsafe tricks that they should know better than to use. I think a C-style cast does it, but then a C-style cast followed by `delete` will break regardless of whether the standard container is a private base, a public base, or not a base at all! – Steve Jessop Sep 21 '12 at 15:37
  • 1
    @TonyTheLion: `they won't destroy properly when inherited from` - this sounds like cargo cult programming. Your concern only applies to cases where a derived class is destroyed via a base class pointer. This is not possible with private inheritance. – Frerich Raabe Sep 21 '12 at 15:39
  • @FrerichRaabe: Yes you're right, I was wrong. I didn't know that private inheritance is essentially the same as composition. – Tony The Lion Sep 21 '12 at 15:40
  • 1
    FWIW, you probably shouldn't think of it as "making `iterator` available", you should think of it as "providing an `iterator`", which because `B` is implemented using `deque`, naturally could be a `deque::iterator`. Amounts to the same thing in the end, though. – Steve Jessop Sep 21 '12 at 15:56
  • @FrerichRaabe: It actually is. The `private` vs. `public` access specifiers only reduces the scope in which things can go wrong, but it does not solve the issue. The class (or a friend of it) can pass itself to a function that claims ownership of the `deque` object and calls `delete` internally. Being `private` greatly reduces the risk from *any code* to just *code with access to private*, but the issue is still there. Note that the *cargo cult* claim can be applied both ways here :) – David Rodríguez - dribeas Sep 21 '12 at 16:06
  • @DavidRodríguez-dribeas: Right, I was being imprecise. However, code with access to the private scope is code which conceptually belongs to the class (possibly even by the same author) and *he* hopefully knows what he's doing. In particular, he should understand that private inheritance is *implementation* reuse as opposed to *interface* reuse, so he shouldn't try to pass a `B*` to code which works with a `std::deque*`. – Frerich Raabe Sep 21 '12 at 17:19

1 Answers1

13

You have to promote this iterator class.

Use using keyword in public section.

class B : private std::deque<A>
{ ... 
 public:
   using std::deque<A>::iterator;    
};

The same for other types as well as other functions from implementation base class(es).

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • 2
    No, you just don't inherit from a STL container – Tony The Lion Sep 21 '12 at 15:28
  • 6
    @TonyTheLion private inheritance is a part of C++ language. Maybe composition is better than this from design point of view - but this is just easier to use. – PiotrNycz Sep 21 '12 at 15:33
  • 1
    The only real issue is if you try and treat your object as an STL container polymorphically, which you won't if you're inheriting privately. STL containers probably don't have virtual destructors, so you'll end up slicing your objects. – bstamour Sep 21 '12 at 19:06