Абстрактный класс С++: чистый виртуальный ковариантный возвратC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Абстрактный класс С++: чистый виртуальный ковариантный возврат

Сообщение Anonymous »

Во-первых, я должен сказать, что ненавижу шаблоны.... из-за них получается нечитаемый сложный код.... не говоря уже о сообщениях об ошибках длиной в 5000000 строк, с 10000 возможностей, и это занимает много времени, чтобы понять что-то, что в конце тривиально и выдает только одно сообщение об ошибке на простом C++.
Но я столкнулся с проблемой, которую не знаю, как решить:
Я устал от бедности поддержка Unicode для C++, они создали char8_t, но это всего лишь своего рода uint8_t, который не может обрабатывать многобайты.... и не говоря уже о сломанных u8string, u8string_view и других "stl Basic_string": они не обеспечивают границы utf-8, вы можете создать подстроку, заканчивающуюся в середине последовательности utf8 или начинающуюся в середине другой или и то, и другое....
поэтому я пишу небольшую библиотеку, чтобы правильно обрабатывать ее, соблюдая концепцию «кодовой точки»: у меня есть u8CodepointView, u16CodepointView, u32CodepointView, которые позволяют получать доступ к кодовым точкам без риска разбить многобайты и позволяют проверять. Они доступны только для чтения без копирования. Это дочерний класс базового абстрактного класса utfCodepointView
тогда у меня такой же, но изменяемый: u8Codepoint... u8string.... весь доступ для чтения вынужден проходить через *View, чтобы избежать сломанного текущего дизайна stl string_view и строки, которые дублируют большую часть доступа (но это нормально, поскольку концепция представления появилась позже из-за неэффективности концепции строки). Также я реализовал способ использования обычного API C++ (cout, cin....), поскольку строка, которая не отображается, бесполезна. поэтому мой тип можно безопасно явно привести к std::string и другим типам C++ stl.
проблема в том, что я хочу, чтобы utfStringView принудительно реализовывал некоторый API, а также реализовывал некоторые общие функции, которые используют указатель/ссылку на этот базовый класс для работы с u8string, u16string, u32string, не заботясь о том, что позади.... сравнение строк, REAL сравнение строк, например, u8string и u16string, изменение содержимого строки... и т. д... в большинстве случаев преобразование типов Appart, мне не нужно беспокоиться, если это utf8 utf16 utf32(ucs) позади... в конце все они представляют собой последовательность кодовых точек.
некоторые из этих функций

Код: Выделить всё

class utfStringView {
public :
virtual utfCodepointView operator[] (const cpidx &aIdx) = 0;
virtual utfStringView substr(const cpidx& aStart, size_t aCount) = 0;
};
Тип cpidx — это просто оболочка int, позволяющая мне переопределять функции, здесь нет ничего интересного. Просто обходной путь, позволяющий получить доступ как на уровне байтов, так и на уровне кодовых точек, используя беззнаковый индекс int.
возьмем, например,

Код: Выделить всё

 virtual utfCodepointView operator[] (const cpidx &aIdx) = 0;
он возвращает aIdx codepointView, но codepointView может быть экземпляром u8CodepointView, u16CodepointView, u32CodepointView.... и все они имеют свои собственные виртуальные функции validate(), size().
поэтому, если я хочу получить размер кодовой точки utf-8 шириной 3 байта в позиции 10 строка, выполняющая lString[10].size(). Мне нужно использовать ковариантный тип возврата: если класс utfCodepointview не был чисто абстрактным классом, возвращаемое значение будет вызывать только utfCodepointview::size(), а не u8CodepointView::size(). И поскольку я сделал его абстрактным, я не могу создать экземпляр объекта этого типа.
поэтому мне придется двигаться чтобы

Код: Выделить всё

 virtual utfCodepointView* operator[] (const cpidx &aIdx) = 0;

Код: Выделить всё

 virtual utfCodepointView& operator[] (const cpidx &aIdx) = 0;
но это подводит меня к проблеме на всю жизнь: я не хочу выделять новый объект, потому что объекты utfCodepointView созданы легковесными и позволяют эффективно копировать (у них есть только два члена: указатель на данные и размер). Итак, возврат указателя.... который уничтожит всю эффективность путем выделения, удаления... для операции регистра с двумя процессорами... и чего-то, к чему большую часть времени будет осуществляться доступ, а затем отбрасываться для доступа к следующему, это нонсенс! Я просто потрачу время на выделение и удаление 2-байтовых объектов...
и возврат ссылки... на что? объект может быть только локальной переменной, поэтому уничтожается при возврате оператора.... я не могу сделать его членом, потому что он не будет потокобезопасным, иначе мне придется защищать его с помощью мьютекса.... и снова потеряю всю эффективность....
то же самое происходит с функцией substr...
единственное решение, которое я вижу, - это сделать utfStringView шаблоном... и мне это не нравится....

Код: Выделить всё

template
class utfStringView
{
public:
constexpr virtual BaseCodepoint operator[] (const cpidx &aIdx) = 0;
constexpr virtual BaseSTring substr(const cpidx& aStart, size_t aCount) = 0;
}
и это также не позволит мне полностью использовать полиморфизм в производном объекте utfStringView для работы с u8string, u16string, u32string таким же образом, поэтому мне придется писать все остальные общие функции в шаблоне....
кстати, я перешел на c++23, потому что мне нравится constexpr.... и некоторые действительно хорошие функции constexpr есть только в c++23.... Итак, если есть что-то, что меня спасает в стандарте и о чем я не знаю.... Я не ограничен версией стандарта...
поэтому мой вопрос: есть ли способ сделать это без шаблона? сохраняя полиморфизм и позволяя мне работать со строками, не заботясь о том, что за этим стоит....
спасибо и с уважением

Подробнее здесь: https://stackoverflow.com/questions/798 ... ant-return
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»