Вот у меня есть класс UtfIterator, который при разыменовании возвращает 32ух-битный Unicode символ, разбирая UTF8 последовательность по char указателю, который хранит у себя, и соответственно, всякие игры c &*it выдадут лажу.
Также у меня в те же функции может быть передан итератор от вектора char или строки, или вообще голые указатели.
Я хочу из любого типа итераторов одинаковым способом получить const char*.
Здравствуйте, Marty, Вы писали:
M>Здравствуйте!
M>Вот у меня есть класс UtfIterator, который при разыменовании возвращает 32ух-битный Unicode символ, разбирая UTF8 последовательность по char указателю, который хранит у себя, и соответственно, всякие игры c &*it выдадут лажу.
M>Также у меня в те же функции может быть передан итератор от вектора char или строки, или вообще голые указатели.
M>Я хочу из любого типа итераторов одинаковым способом получить const char*.
M>Есть ли для этого каноничное решение?
Чтобы продать что-нибудь ненужное, нужно сначала купить что-нибудь ненужное, а у нас денег нет
Чтобы откуда ни будь получить const char* он там изначально должен быть, а у тебя там 32ух-битный Unicode символ. Вот его вполне можно и получить
Re[2]: Можно ли и как канонично получить из итератора тип элемента последователь
Здравствуйте, vopl, Вы писали:
V>Чтобы откуда ни будь получить const char* он там изначально должен быть, а у тебя там 32ух-битный Unicode символ. Вот его вполне можно и получить
У меня в итераторе const char* хранится, 32ух-битный Unicode символ собирается по UTF8-строке и при разыменовании возвращается по значению
Здравствуйте, Marty, Вы писали:
M>Здравствуйте!
M>Вот у меня есть класс UtfIterator, который при разыменовании возвращает 32ух-битный Unicode символ, разбирая UTF8 последовательность по char указателю, который хранит у себя, и соответственно, всякие игры c &*it выдадут лажу.
M>Также у меня в те же функции может быть передан итератор от вектора char или строки, или вообще голые указатели.
M>Я хочу из любого типа итераторов одинаковым способом получить const char*.
M>Есть ли для этого каноничное решение?
Ну так конечно, у тебя же последняя перегрузка невыводимая в принципе. Ты прикинь, одновременно 100500 классов контейнеров могут иметь одинаковые типы итераторов и какой тип контейнера должен при этом вывестись?
Здравствуйте, rg45, Вы писали:
M>>Никак не понимает, что я хочу. Как объяснить?
R>Ну так конечно, у тебя же последняя перегрузка невыводимая в принципе.
Ну я не настоящий сварщик
R>Ты прикинь, одновременно 100500 классов контейнеров могут иметь одинаковые типы итераторов и какой тип контейнера должен при этом вывестись?
А мне на тип контейнера наплевать, мне интересен тип, который получается при разыменовании ContainerType::iterator, при этом, если мне дали итератор не последовательногопроизвольного доступа, и я начал с ним работать — эта проблема меня не волнует, я не хочу парится с детектом такой ситуации.
Хотя, был наверное не прав в формулировках. Я исхожу из той концепции, что итератор либо указывает на реальную память, и при разыменовании возвращает что-то, с чем можно сделать &*it, и какие-то другие типы итераторов, которые надо отдельно обрабатывать.
Тут подумалось, можно попробовать:
— является ли итератор простым указателем
— можно ли сделать &*it
— огород для других типов итераторов
но не уверен, что компилятор меня поймёт, да и как реализовать, пока не очень понимаю.
Наверное, надо копнуть на тему enable_if c decltype/decay по типу *it
R>На С++20 эта задача решается легко и изящно:
А на С++17?
Мне бы хотелось привести к указателю на char
— итератор любого стандартного контейнера с произвольным доступом, который содержит элементы типа char или интегрального тип такого же размера (по размеру — желательно, но не обязательно)
— сам char* или const char*
— свой итератор, который при разыменовании возвращает не ссылку на элемент по хранимому в нем char-указателю, а произвольное значение by value. У последнего типа итератора есть метод rawPtr
R>Можно сделать аналог и на SFINAE, но там чуть больше пыли глотать придётся.
Ну, намекни, куда копать, мне пока не понятно. Сделал совсем тупо для базовых кейсов — тоже не прокатило:
Здравствуйте, Marty, Вы писали:
R>>Можно сделать аналог и на SFINAE, но там чуть больше пыли глотать придётся. M>Ну, намекни, куда копать, мне пока не понятно. Сделал совсем тупо для базовых кейсов — тоже не прокатило:
Ну, как-то так. И обрати внимание, если ты хочешь, чтоб работал ADL, перегрузку rawConstCharPtrFromIterator для UtfInputIterator нужно внести в неймспейс marty::utf.
Здравствуйте, Marty, Вы писали:
M>Можно ли и как канонично получить из итератора тип элемента последовательности? M>Я хочу из любого типа итераторов одинаковым способом получить const char*.
Это две совершенно разные задачи. Вторая решаема (я показал
Первая же задача нерешаема в принципе. Давай рассмотрим такой псевдокод:
// Имеем несколько классов контейнеров.
// Каждый класс содержит внутри определения своих итераторов.
// И разумеется уникальность типов итераторов никто не гарантирует.struct Containter1 { using iterator = int*; };
struct Containter2 { using iterator = int*; };
struct Containter3 { using iterator = int*; };
// Допустим, что по типу итератора можно вывести тип контейнера.template <typename ContainerType>
void foo(ContainerType::iterator);
int main()
{
// Попоробуем заюзать это дело.
Container1::iterator it1;
Container2::iterator it2;
Container3::iterator it3;
// Вот в этом месте самое время обратить внимание на то,
// что объекты it1, it2, it3 имеют один и тот же тип - int*.
// И каким образом компилятор должен понять, что в следующих
// случаях должны быть выведены различные типы контейнеров и какие именно?
foo(it1);
foo(it2);
foo(it3);
}
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, rg45, Вы писали:
R>>>Можно сделать аналог и на SFINAE, но там чуть больше пыли глотать придётся. M>>Ну, намекни, куда копать, мне пока не понятно. Сделал совсем тупо для базовых кейсов — тоже не прокатило:
R>Ну, как-то так. И обрати внимание, если ты хочешь, чтоб работал ADL, перегрузку rawConstCharPtrFromIterator для UtfInputIterator нужно внести в неймспейс marty::utf.
R>https://coliru.stacked-crooked.com/a/456031d81cb952ce
Здравствуйте, Marty, Вы писали:
M>Я хочу из любого типа итераторов одинаковым способом получить const char*. M>Есть ли для этого каноничное решение?
Я бы добавил итератору метод
const char* base()
(по аналогии с std::reverse_iterator)
Я так понимаю, все UtfIterator'ы только константные и поддержки *it = 'a' не будет? Вот без этого не интересно.
И каждый день — без права на ошибку...
Re[2]: Можно ли и как канонично получить из итератора тип элемента последователь
Здравствуйте, B0FEE664, Вы писали:
M>>Я хочу из любого типа итераторов одинаковым способом получить const char*. M>>Есть ли для этого каноничное решение? BFE>Я бы добавил итератору метод const char* base() (по аналогии с std::reverse_iterator)
Ну, rawPtr() таки возвращает не то, что base() в std::reverse_iterator, и я не хочу навешивать на стандартное имя метода то, что оно не делает — проверки по SFINAE или новомодные концепты могут детектить не то, что бы им хотелось на самом деле.
Но begin()/end() есть, мой итератор может выглядеть как range контейнер, от текущего указателя на char'ы до заданного конца
BFE>Я так понимаю, все UtfIterator'ы только константные и поддержки *it = 'a' не будет? Вот без этого не интересно.
Для вывода есть UtfOutputIterator, из InputIterator в OutputIterator можно скопировать как while(inB!=inE) *outIt++ = *inB++; , так и при помощи std алгоритмов: std::copy(inB, inE, outIt), или, при нужде что-то поменять, std::transform, как вариант.
Модифицировать исходные строки, вставляя/заменяя туда/там Unicode символы, которые могут иметь длину от одного до шести байт в UTF-8 — не вижу смысла — несколько замен/вставок в начале/середине строки могут как привести к переаллокации, так и гарантированно приведут к перемещениям хвостов контейнеров, в которых это хранится. Овчинка выделки не стоит, и даже вредна. Лучше для результата зарезервировать место один раз, с возможным запасом на результат модификации, это будет эффективнее.
Здравствуйте, rg45, Вы писали:
BFE>>Я так понимаю, все UtfIterator'ы только константные и поддержки *it = 'a' не будет? Вот без этого не интересно. R>Ну почему, само название UtfInputIterator намекает на существование UtfOutputIterator.
OutputIterator — это относительно просто, а вот изменение по месту — нетривиальная задача, от воплощения которой Marty тут же отказался. По работе я не сталкиваюсь с редакторами текста, так что для меня задача не актуальна и я не могу оценить востребованность такой операции, так что может оно и не надо...
И каждый день — без права на ошибку...
Re[4]: Можно ли и как канонично получить из итератора тип эл
Здравствуйте, B0FEE664, Вы писали:
BFE>OutputIterator — это относительно просто, а вот изменение по месту — нетривиальная задача, от воплощения которой Marty тут же отказался. По работе я не сталкиваюсь с редакторами текста, так что для меня задача не актуальна и я не могу оценить востребованность такой операции, так что может оно и не надо...