Сделать операторы сравнения контейнеров независимыми от типа аллокатора

smertigdon
smertigdon

Мотивация следующая. Следующий код не будет компилироваться 

#include <memory>
#include <vector>
 
template <class T>
struct custom_allocator : std::allocator<T> {};
 
int main() {
	std::vector<int, std::allocator<int>> a;
	std::vector<int, custom_allocator<int>> b;
	a == b; // compilation error, no match for 'operator=='
	return 0;
}

Причина очевидна - оператор сравнения определён лишь для объектов идентичных типов, что включает в себя и типы аллокаторов. Однако сам аллокатор не влияет на внутреннюю структуру контейнера и, следовательно, не должен влиять на логику различных операций над контейнером, которые его не меняют (точнее, на более широкий класс - которые не вызывают выделения памяти).

Предложение следующее - заменить сигнатуру операторов сравнения с 

template <class T, class Allocator>
bool operator==(const std::vector<T, Allocator>& lhs, const std::vector<T, Allocator>& rhs) { ... }

на

template <class T, class Allocator1, class Allocator2>
bool operator==(const std::vector<T, Allocator1>& lhs, const std::vector<T, Allocator2>& rhs) { ... }

Аналогично для всех прочих операторов сравнения, а также для всех контейнеров. 

Обратную совместимость это не ломает, зато немного упрощает жизнь разработчику.

 

P.S. Есть ощущение, что данную идею можно развить и дальше, например, на конструкторы копирования, операторы присваивания (не учитывая их перемещающие аналоги). Возможно, стоит обдумать какую-то концепцию, которая позволит вырезать тип аллокатора из типа-контейнера и оперировать универсальным образом везде, где не происходит перераспределения памяти.

22
рейтинг
6 комментариев
yndx-antoshkka
Мне идея нравится. Если нужна помощь с написанием proposal - говорите, помогу.
yndx-antoshkka
Antervis
А может имеет смысл сразу ориентироваться на Concepts && Ranges? В том плане, что два контейнера разных типов (vector<int>, list<int>) тоже могут сравниваться лексикографически. Что-то вроде inline bool operator == (const Container &lhs, const Container &rhs) { return equal(lhs,rhs); }
Antervis
yndx-antoshkka
Antervis, стоит проработать оба варианта и дать комитету выбор между "для каждого контейнера добавляем операторы сравнения" и "операторы сравнения для всех контейнеров сразу"
yndx-antoshkka
Antervis
yndx-antoshkka, так ведь одно является подмножеством второго
Antervis
Will Code For Food
> Есть ощущение, что данную идею можно развить и дальше, например, на конструкторы копирования, операторы присваивания

Нельзя развить дальше. Конструктор копирования и оператор присваивания не может быть шаблонным.
Will Code For Food
Will Code For Food
> Есть ощущение, что данную идею можно развить и дальше, например, на конструкторы копирования

Добавлю ещё, что есть темплейтный конструктор, принимающий input-итераторы. Хоть вектором с другим аллокатором инициализируйте, хоть другим контейнером.
Ну а про std::equal уже написали.

Сравнение и инициализацию ещё со времён C++98 можно делать гораздо более общим способом, чем просто не различая аллокаторы у контейнеров одного и того же вида.
Will Code For Food
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).