Возможность создать POD-структуры, для которых тип определяется расположением элементов, concept structs
Идея является альтернативой/дополнением к https://github.com/cpp-ru/ideas/issues/485
Сама идея
Сделать возможным, чтобы часть POD-типов была одинаковой не когда полностью совпадают имена типов и членов типа, а только когда совпадает расположение каждого типа внутри. Пример
concept struct Coords{
float x; //имена не играют роли
float y;
float len() { return std::hypot(x,y); }
};
concept struct xy{
float X;
float Y;
float len_sq() { return x*x + y*y; }
};
std::vector<Coords> a{ {1,2}, {3,4}, {5,6} };
std::vector<xy> b = std::move(a); // Должно компилироваться
Поскольку есть тонны написанного кода, в который новомодные concept struct никто не добавит, может быть, стоит явно сказать компилятору про совпадения типов
struct Coords{
float x; //имена не играют роли
float y;
float len() { return std::hypot(x,y); }
};
struct xy{
float X;
float Y;
float len_sq() { return x*x + y*y; }
};
concept struct coords = {Coords, xy}; // не знаю, как не использовать новые ключевые слова
Применение
Один в один с https://github.com/cpp-ru/ideas/issues/485
Существует достаточно много разных структур координат или rgb-цвета и других подобных, с одинаковым расположением элементов но формально разными типами. И хотя для простых указателей на них ещё можно делать reinterpret_cast и надеяться на лучшее, для вещей вроде vector<vector<Coords>> фокус уже не прокатывает.
Возможные проблемы
Формальное определение одинаковости. Особенно с учётом всех константно-волатильных указателей. Вряд ли смогу сформулировать сам.
Возможно, тоже будут какие-то проблемы со строгим разыменованием, но опять же, не уверен.
Определённо прибавиться работы блокам проверки одинаковости типов, не представляю сколько там её вывалиться. Как вариант, просто объявить любое несовпадение UB и внутри пусть компилятор будет уверен, что одно точно алиас другого до того дня, когда проверки реально введут.
Как я понимаю, проблема такая - есть два разных типа данных (в смысле что один тип не является алиасом другого), и надо сделать две вещи:
- Удостовериться, что у них одинаковый layout в памяти
- Делать "быстро" вещи, которые сейчас делаются "медленно" (например, создание нового вектора и ручное заполнение вместо
std::move(x))
Первый пункт в C++XX можно будет выполнить через рефлексию - сравнить количество членов структуры и их типы. Даже не обязательно для POD-типов, можно рекурсивно проверять состав "сложных" типов.
Второй пункт можно выполнить полу-нелегальным образом - как я подозреваю, std::vector<Coords> и std::vector<xy> имеют идентичное представление на стеке и в куче. Поэтому можно будет сделать псевдо-move, скопировав значение стека, как-то так:
std::vector<Coords> v1 = ...; // как-то заполняем...
std::vector<xy> v2;
std::memcpy(&v2, &v1, sizeof(decltype(v1));
// теперь надо как-то сделать амнезию у v1, чтобы он в деструкторе ничего не трогал
// возможно std::memset(&v1, 0, sizeof(decltype(v1));