Проблема намного сложнее, чем кажется. Поскольку тип распределителя является частью типа объекта, допускается малое взаимодействие между типами, которые отличаются только распределителем. Первый пример, который приходит на ум, состоит в том, что функция, которая принимает значение std::string
по постоянной ссылке, не может принимать строку, которая использует другой распределитель. Один из таких случаев - при строительстве объектов. На самом деле это, наверное, сложнее.
Рассмотрим, например, следующий код:
// Assume that you could construct from a different allocator
std::vector<int, allocator1> f() {
std::vector<int, allocator2> r;
// fill in
return r;
}
int main() {
std::vector<int, allocator3> x = f();
}
Считают, что это allocator1
std::allocator<int>
(т.е. Распределитель по умолчанию), что allocator2
использует локальную арену в стеке, и что allocator3
может использовать совместно используемую память. Теоретически код достаточно прост, вектор r
создается и заполняется данными, заявление возвращения нового временного создается копирования из r
, и, наконец, x
строится копирования от временного. Проблема в том, что стандарт позволяет (и компиляторам) избегать копирования в максимально возможной степени. В приведенном выше примере (и игнорировании распределителей) компилятор будет лидировать в обеих копиях и создавать буфер только один раз, что является быстрым и эффективным. Но при том, что распределители потенциально могут быть разными, NRVO и другие типы copy-elision должны быть отключены. (Если эти оптимизации включены, x
в основном будет использовать allocator2
, с локальной ареной, которая уже была уничтожена, что вызвало неопределенное поведение).
Включая построение копии из контейнеров с одним распределителем в другой, вы можете оказаться в беспорядке или в более глубоком беспорядке, чем мы уже находимся в текущем стандарте, где вы можете вызвать всевозможные интересные проблемы с помощью генераторов с поддержкой состояния (скажем, что вы используете распределяющие потоки, и что вы вносите данные в общую очередь, вы можете получить один поток, содержащий объект, созданный распределителем потоков для другого потока, и потому, что точка использования per- нить распределители, избегают раздоров на замках, вы могли бы создать условия гонки по-видимому, безопасный код ....
Это старый р создание комитета C++ Towards a better allocation model, что вызывает некоторые проблемы с моделью распределения C++ 03 и предлагает тип полиморфного распределителя (который имеет проблемы с его собственными).Это делает интересным чтение, но остерегайтесь деталей, не все так хорошо, как кажется, и есть немало ошибок в использовании любой опции (или версии C++ 11, которая похожа на C++ 03 версия)
Возможно, было бы непросто реализовать функцию шаблона, которая преобразует типы шаблонов std, которые отличаются только их распределителем. (Я не говорю, что этот вопрос недействителен - это, конечно же, - только то, что количество кода, необходимого для работы вокруг этого, не должно быть много.) – cdhowie
Да, поскольку преобразование не может быть свободным оператором I я должен явно преобразовать всю свою кодовую базу, но все равно может быть единственным решением :( – Ylisar
Да, автоматическое преобразование будет невозможно, к сожалению. – cdhowie