I was reading the documentation of std::sub_match<BidirectionalIterator> and saw that it publicly inherits from std::pair<BidirectionalIterator, BidirectionalIterator>. Since a sub_match is simply a pair of iterators into a sequence of characters, with some additional functions, I can understand that it is implemented with a pair, but why use public inheritance?
The problem with inheriting publicly from std::pair<T,U> is the same as inheriting publicly from most other standard classes: they are not meant to be manipulated polymorphically (notably they do not define a virtual destructor). Other members will also fail to work properly, namely the assignment operator and the swap member function (they will not copy the matched member of sub_match).
Why did Boost developers and then the committee decided to implement sub_match by inheriting publicly from pair instead of using composition (or private inheritance with using declarations if they wanted to keep member access through first and second)?
It’s an interesting question. Presumably, they considered it safe
because no one would ever dynamically allocate one anyway. About the
only way you’re going to get
sub_matchobjects is as a return valuefrom some of the functions of
basic_regex, or as copies of othersub_match, and all of these will be either temporaries or localvariables.
Note that it’s not safe to keep
sub_matchobjects around anyway, sincethey contain iterators whose lifetime… doesn’t seem to be specified in
the standard. Until the
match_resultsobject is reused? Until thestringoperand to the function which filled in thematch_resultsobject is destructed? Or?
I’d still have avoided the public inheritence. But in this case, it’s
not as dangerous as it looks, because there’s really no reason you’d
ever want to dynamically allocate a
sub_match.