Почему std::vector::get_allocator() возвращает по значению?
К моему удивлению, я получил ошибку при попытке использовать std::vector::get_allocator()
с не копируемым распределителем. Почему std::vector::get_allocator()
вернуть по значению, а не по ссылке?
template<typename T>
class nc_allocator {
public:
using value_type = T;
nc_allocator(nc_allocator const&) = delete;
nc_allocator& operator=(nc_allocator const&) = delete;
// Other required members.
};
std::vector<int, nc_allocator<int>> v;
// boom: use of deleted function
// 'nc_allocator<T>::nc_allocator(const nc_allocator<T>&) [with T = int]'
v.get_allocator();
2 ответа
Я получил ошибку при попытке использовать
std::vector::get_allocator()
с не копируемым распределителем.
Стандарт запрещает вам это делать. Требования к распределителю в 17.6.3.5
утверждают, что распределитель должен быть копируемым.
X a1(a); Shall not exit via an exception.
post: a1 == a
X a1(move(a)); Shall not exit via an exception.
post: a1 equals the prior value
of a.
Таким образом, возвращение по значению является правильным способом возврата распределителя с учетом требований распределителя, определенных стандартом.
Я не уверен, почему это требование, но если бы допускались не копируемые распределители, оптимизация пустой базы больше не работала бы.
Стандарт просто диктует так:
[C++11: 23.2.1/7]:
[..] Во всех типах контейнеров, определенных в этом разделе, член get_allocator() возвращает копию распределителя, использованного для создания контейнера, или, если этот распределитель был заменен, копию самой последней замены [..]
Я подозреваю, что @ Вон прав в своей гипотезе, что распределители предназначены для использования в качестве "ручек".
По очень свободной аналогии, вы когда-нибудь могли бы написать не копируемый функтор для использования со стандартными алгоритмами?