Почему std:: sub match публично наследуется от std:: pair?

Я читал документацию std::sub_match<BidirectionalIterator> и увидел, что он публично наследует от std::pair<BidirectionalIterator, BidirectionalIterator>. Сsub_match - это просто пара итераторов в последовательности символов, с некоторыми дополнительными функциями, я могу понять, что он реализован с помощью pair, но зачем использовать открытое наследование?

проблема с наследованием публично от std::pair<T,U> это то же самое, что и наследование публично от большинства других стандартных классов: они не предназначены для полиморфного манипулирования (в частности, они не определяют виртуальный деструктор). Другие члены также не будут работать должным образом, а именно оператор присваивания и функция-член swap (они не будут копировать matched член sub_match).

Почему разработчики Boost, а затем комитет решил реализовать sub_match публично наследовать от pair вместо использования композиции (или частного наследования с использованием деклараций, если они хотели сохранить доступ к членам через first и second)?

5 ответов


это интересный вопрос. Предположительно, они считали это безопасным потому что никто никогда не будет динамически распределять их в любом случае. Об единственный способ получить sub_match objects является возвращаемым значением из некоторых функций basic_regex, или копии иных sub_match, и все они будут либо временными, либо локальными переменная.

обратите внимание, что это не безопасно держать sub_match объекты вокруг в любом случае, так как они содержат итераторы, срок службы которых... не кажется указано в стандарт. Пока


потому что C++ не может наследовать интерфейс без публичного наследования. Вы можете наследовать реализацию с частным наследованием, но тогда все является частным. Если вы хотите тот же интерфейс, что и std::pair вы должны быть a std::pair.

кроме того, рассмотрим это. Это, очевидно, неопределенное поведение:

std::sub_match<BidirectionalIterator> theMatch = ...;
std::pair<BidirectionalIterator> *pMatch = &theMatch;
delete pMatch;

но вот это:

std::sub_match<BidirectionalIterator> theMatch = ...;
std::pair<BidirectionalIterator> *pMatch = &theMatch.pair;
delete pMatch;

почему первый из них гораздо больше беспокоит, чем второй?

sub_match и pair являются легкими объектами (в зависимости от их содержания, конечно). Они предназначены для копирования или передачи по ссылке, все из которых на 100% безопасны. Существует мало, если есть какая-либо причина, чтобы выделить их в куче и использовать их через указатели. Поэтому, хотя я понимаю вашу озабоченность, я думаю, что это вряд ли произойдет в любом реальном коде.


вот что regexавтор должен сказать об этом: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1429.htm#matches_discussion

боюсь, ничего особенного в вашем вопросе.

Я бы предположил, что это решение было компромиссом между изобретением колеса и введением небольшого риска неправильного использования. Обратите внимание, что в общем случае нет необходимости создавать sub_match они возвращались из . Сверх того пары итераторы - очень практичный способ реализации диапазонов.


потому что не нужен виртуальный деструктор? ;-)


Если std::sub_match<BidirectionalIterator> не имеет собственного состояния, тогда это нормально для него наследовать от std::pair. Только не дома.