Информация об изменениях

Сообщение Re[2]: Аллокатор для std::[unordered_][multi]map от 08.12.2015 18:29

Изменено 08.12.2015 22:20 watchmaker

Здравствуйте, Mr.Delphist, Вы писали:

MD>Здравствуйте, Alexander G, Вы писали:


AG>>А можно там не выписывать этот тип pair<const Key, Value> как шаблонный параметр аллокатора?

AG>>Ну, т.е. написать какой-нибуь char вместо типа? Он же всё равно внутри ребиндится.

MD>Ну, если рассуждать в подобном ключе далее, то вся система типов — "не нужна"TM, ибо вполне можно жить на "void*".


Не надо передёргивать.
Изначальный интерфейс аллокаторов в С++ очень плох. И устарел.
В нём все аллокаторы одного типа должны были быть эквивалентны друг-другу, то есть гарантированно работатать со стандартными контейнерами могли лишь stateless аллокаторы. Хочешь завести в программе пару пулов строчек? Перебьёшься! То есть даже нельзя надёжно и эффективно написать с независимыми аренами
vector<string, my_arena_allocator<string> > v1(my_arena_allocator<string>(arena1));
vector<string, my_arena_allocator<string> > v2(my_arena_allocator<string>(arena2));
Ибо по стандарту строку, которую веделил аллокатор my_arena_allocator<string>(arena1), должен уметь разрушать любой другой экземпляр, например my_arena_allocator<string>(arena2) или даже my_arena_allocator<string>(NULL), что в общем-то никак не способствует эффективности. В результате чего нужно либо отказываться от std::vector (и прочих контейнеров STL), либо связывать все экземпляры аллокаторов между собой, чтобы один аллокатор мог всегда найти другой экземпляр, который изначально создал объект, и передать ему его для уничтожения (подобно тому, как это сделано в boost::fast_pool_allocator с синхронизацией через mutex), — и это ужасно.

Но зато интерфейс аллокаторов позволяет поддерживать одновременно near и far pointers. Ну очень востребованная возможность в современном программировании.
Вот что важнее, быстрый и эффективный memory_pool или объязательная поддержка устаревших/редких моделей памяти даже для тех, кто ими не пользуется?
К счастью в C++11 аллокаторы всё же были переработаны. Пусть и и не все многочисленные предложения удалось воплотить. Но хотя бы stateful-аллокаторы теперь разрешены в стандартных контейнерах!

И изначальный вопрос в целом правильный. Точно также можно построить реализацию контейнеров, в которой узаконить объязательный rebind аллокатора, и тогда указывать типы вручную не понадобится — и код станет короче (может быть даже выразительнее, если синтаксический сахар в виде std::allocator<auto> до кучи добавить). Наверное, в некоторых хитрых местах, завязанных на не-плоскую память, может что-то поломаться и понадобится что-то дописать — там код станет длиннее. Кажется, что в среднем было бы выгоднее иметь обязательный rebind и более лаконичный код. И даже если кому-то понадобится писать полный и точный тип, то эта возможность у них останется. Сейчас же типы выписывать вынуждены все.

Так что хоть формальный запрет и есть, но у него нет никакого сакрального смысла — это просто ещё одно из неудачных решений ранних версий языка, которое, к сожалению, уже нельзя легко изменить.
Здравствуйте, Mr.Delphist, Вы писали:

MD>Здравствуйте, Alexander G, Вы писали:


AG>>А можно там не выписывать этот тип pair<const Key, Value> как шаблонный параметр аллокатора?

AG>>Ну, т.е. написать какой-нибуь char вместо типа? Он же всё равно внутри ребиндится.

MD>Ну, если рассуждать в подобном ключе далее, то вся система типов — "не нужна"TM, ибо вполне можно жить на "void*".


Не надо передёргивать.
Изначальный интерфейс аллокаторов в С++ очень плох. И устарел.
В нём все аллокаторы одного типа должны были быть эквивалентны друг-другу, то есть гарантированно работатать со стандартными контейнерами могли лишь stateless аллокаторы. Хочешь завести в программе пару пулов строчек? Перебьёшься! То есть даже нельзя надёжно и эффективно написать с независимыми аренами
vector<string, my_arena_allocator<string> > v1(my_arena_allocator<string>(arena1));
vector<string, my_arena_allocator<string> > v2(my_arena_allocator<string>(arena2));
Ибо по стандарту строку, которую веделил аллокатор my_arena_allocator<string>(arena1), должен уметь разрушать любой другой экземпляр, например my_arena_allocator<string>(arena2) или даже my_arena_allocator<string>(NULL), что в общем-то никак не способствует эффективности. В результате чего нужно либо отказываться от std::vector (и прочих контейнеров STL), либо связывать все экземпляры аллокаторов между собой, чтобы один аллокатор мог всегда найти другой экземпляр, который изначально создал объект, и передать ему его для уничтожения (подобно тому, как это сделано в boost::fast_pool_allocator с синхронизацией через mutex), — и это ужасно.

Но зато интерфейс аллокаторов позволяет поддерживать одновременно near и far pointers. Ну очень востребованная возможность в современном программировании. Особенно с учётом того, что как оказалось, этой возможностью всё равно не получилось полноценно пользоваться: сам Степанов в интервью приводит пример почему этот механизм не работает.
Вот что важнее, быстрый и эффективный memory_pool или объязательная поддержка устаревших/редких моделей памяти даже для тех, кто ими не пользуется?
К счастью в C++11 аллокаторы всё же были переработаны. Пусть и и не все многочисленные предложения удалось воплотить. Но хотя бы stateful-аллокаторы теперь разрешены в стандартных контейнерах!

И изначальный вопрос в целом правильный. Точно также можно построить реализацию контейнеров, в которой узаконить объязательный rebind аллокатора, и тогда указывать типы вручную не понадобится — и код станет короче (может быть даже выразительнее, если синтаксический сахар в виде std::allocator<auto> до кучи добавить). Наверное, в некоторых хитрых местах, завязанных на не-плоскую память, может что-то поломаться и понадобится что-то дописать — там код станет длиннее. Кажется, что в среднем было бы выгоднее иметь обязательный rebind и более лаконичный код. И даже если кому-то понадобится писать полный и точный тип, то эта возможность у них останется. Сейчас же типы выписывать вынуждены все.

Так что хоть формальный запрет и есть, но у него нет никакого сакрального смысла — это просто ещё одно из неудачных решений ранних версий языка, которое, к сожалению, уже нельзя легко изменить.