Почему перегрузка оператора & () запрещена для классов, хранящихся в контейнерах STL? - PullRequest
7 голосов
/ 27 апреля 2010

Внезапно в этой статье ("проблема 2") Я вижу утверждение, что Стандарт C ++ запрещает использование контейнеров STL для хранения элементов класса, если этот класс имеет перегруженную operator&().

Перегрузка operator&() действительно может быть проблематичной , но, похоже, оператор "address-of" по умолчанию может быть легко использован через набор грязно выглядящих приведений, которые используются в boost::addressof() и считаются переносимыми и совместимыми со стандартами.

Почему перегрузка operator&() запрещена для классов, хранящихся в контейнерах STL, пока существует обходной путь boost::addressof()?

Ответы [ 3 ]

6 голосов
/ 27 апреля 2010

Не глядя на ссылки, я полагаю, уловки в boost::addressof() были придуманы задолго до того, как не перегружать унарный префикс & для объектов, которые должны храниться в контейнерах библиотеки std.

Я смутно помню, как Пит Беккер (тогда работавший на Dinkumware над реализацией их стандартной библиотеки) однажды заявил, что каждый, кто перегружает оператор address-of и ожидает, что их реализация стандартной библиотеки все еще работает, должен быть наказан необходимостью реализации стандартной библиотеки, которая Является ли это.

2 голосов
/ 27 апреля 2010

Возможно, потому что проще всего запретить использование перегруженных классов operator & (), чем создавать функцию std :: addressof () и заменять ею каждое использование & в коде контейнера.

1 голос
/ 28 апреля 2010

Стандарт был окончательно доработан в 1998 году, исправления - в 2003 году, тогда как boost::addressof датируется началом 2002 года.

Кроме того, не ясно, что addressof является ответом. Перегрузки operator&() указывают на то, что необработанных указателей следует избегать. Член Allocator::address обеспечивает лучший интерфейс для перехода от Allocator::reference к Allocator::pointer, поэтому в общей теории вы должны иметь возможность вводить переопределение operator& для класса с хорошим поведением с пользовательским распределителем.

Учитывая, что ссылки делают почти все, что делают указатели, а интерфейс Allocator абстрагирует все остальное, необязательно указывать необработанные указатели.

Удобство для разработчиков библиотеки не должно быть проблемой. Плохо определенная семантика Allocator::pointer является проблемой, и то, что я читал до сих пор в C ++ 0x, не проясняет это.

C ++ 0x удаляет любое упоминание operator& из CopyConstructible, и, кроме того, вообще не требует ничего-Constructible для аргументов контейнера - пользователь может придерживаться emplace. Даже для vector требуется только Destructible, хотя я полагаю, что для использования insert или erase потребуется больше.

(Обратите внимание, что в самом строгом чтении перегрузки не запрещены в C ++ 03. Вам просто не разрешено изменять значение или тип встроенной функции.)

...