Почему std :: sub_match <T>публично наследуется от std :: pair <T, T>? - PullRequest
9 голосов
/ 27 октября 2011

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

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

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

Ответы [ 5 ]

5 голосов
/ 27 октября 2011

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

Обратите внимание, что в любом случае хранить sub_match объекты небезопасно, поскольку они содержат итераторы, время жизни которых ... не указано в стандарте.Пока объект match_results не будет повторно использован?До тех пор, пока операнд string функции, которая заполняет объект match_results, не будет уничтожен?Или?

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

3 голосов
/ 27 октября 2011

Потому что 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% безопасно.Существует мало причин для размещения их в куче и использования их через указатели.Поэтому, хотя я понимаю вашу озабоченность, я думаю, что это вряд ли произойдет в любом реальном коде.

3 голосов
/ 27 октября 2011

Вот что говорит об этом regex автор: http://www.open -std.org / jtc1 / sc22 / wg21 / docs / paper / 2003 / n1429.htm # match_discussion

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

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

0 голосов
/ 27 октября 2011

Если std::sub_match<BidirectionalIterator> не имеет собственного состояния, то вполне нормально, что он наследует от std::pair. Но не делай этого дома.

0 голосов
/ 27 октября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...