LINUX.ORG.RU

В Си предложили добавить switch-case для строк

 , ,


0

3

Привет, чат!

Спустя много лет, в язык Си наконец предложено добавить возможность использовать выражение switch-case для строк. Например, можно будет писать вот такое:

const char *s = get_some_string();

switch(s) {
case "this":
  handle_this();
  break;
case "that":
  handle_that();
  break;
default:
  handle_other();
  break;
}

Таким образом, в Си будет чуть меньше способов отстрелить себе ноги.

Ссылка на предложение: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3895.pdf



Последнее исправление: hobbit (всего исправлений: 1)
Ответ на: комментарий от anonymous

Так потребление пиара и нарративчиков, и, главное, распространение оных - как раз и есть прямое «прислужничанье капиталу».

Какистократия была бы невозможна без интеллигенции. Любая интеллигенция всегда стремится напихать этики (разумеется в своём понимании) в места где такой этике вообще нет места. В итоге имеем clown world во все поля, везде и сразу.

Потому что дебила не назали дебилом когда это нужно было сделать, ибо «неинтеллигентно».

Так что Ленин сильно ошибался насчёт «части».

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Могу ещё разницу между интеллигенцией и интеллектуалами разъяснить

Попросим. А так же с приставкой квази-

ant1
()
Ответ на: комментарий от Stanson

Давайте прилепим к кучке байт жирнющий vtbl от std::string

Там указатель на vtable, чел.

с кучей дублирующих функций типа start/front

Там нет start, есть begin. Которая делает совсем не то, что делает front.

будем таскать это всё дальше по коду вместе с каким-нибудь смешным «asdf», который на порядок меньше этой всей красоты.

Для коротких строк std::string и правда будет оверкиллом, соглашусь.

yorshka
() автор топика
Ответ на: комментарий от ant1

Без приставки.

- А чем интеллигент отличается от интеллектуала?
- Различие очень существенное, - ответил он. - Я берусь объяснить только аллегорически. Понимаете, что это значит?
Я кивнула.
- Когда вы были совсем маленькая, в этом городе жили сто тысяч человек, получавших зарплату за то, что они целовали в зад омерзительного красного дракона. Которого вы, наверно, уже и не помните…
Я отрицательно покачала головой. Когда-то в юности я действительно видела красного дракона, но уже забыла, как он выглядел, - запомнился только мой собственный страх. Павел Иванович вряд ли имел в виду этот случай.
- Понятно, что эти сто тысяч ненавидели дракона и мечтали, чтобы ими правила зеленая жаба, которая с драконом воевала. В общем, договорились они с жабой, отравили дракона полученной от ЦРУ губной помадой и стали жить по-новому.
- А при чем тут интелл…
- Подождите, - поднял он ладонь. - Сначала они думали, что при жабе будут делать точь-в-точь то же самое, только денег станут получать в десять раз больше. Но оказалось, что вместо ста тысяч целовальников теперь нужны три профессионала, которые, работая по восемь часов в сутки, будут делать жабе непрерывный глубокий минет. А кто именно из ста тысяч пройдет в эти трое, выяснится на основе открытого конкурса, где надо будет показать не только высокие профессиональные качества, но и умение оптимистично улыбаться краешками рта во время работы…
- Признаться, я уже потеряла нить.
- А нить вот. Те сто тысяч назывались интеллигенцией. А эти трое называются интеллектуалами.

© В.Пелевин «Священная книга оборотня».

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Не читал, пролистал сразу вниз

© В.Пелевин

Спасибо, проблевался. Читать на всякий случай не буду

ant1
()
Ответ на: комментарий от yorshka

Там указатель на vtable, чел.

Чтобы был указатель, надо чтобы vtable где-то была, разве не так?

Там нет start, есть begin. Которая делает совсем не то, что делает front.

Да я помню, что-ли как оно там точно называется? Мне лень лезть в сырцы libstdc++, но одинаковых функций там куча.

Ладно, слазаю. Сходу:

...
       constexpr const_iterator
       begin() const noexcept
       { return this->_M_str; }
...
       constexpr const_iterator
       cbegin() const noexcept
       { return this->_M_str; }
...
       constexpr const _CharT*
       data() const noexcept
       { return this->_M_str; }

...
Stanson ★★★★★
()
Ответ на: комментарий от Stanson

прочитайте внимательно что я назвал: std::string_view

https://en.cppreference.com/cpp/string/basic_string_view

Это максимально простая, понятная, и благодаря этому гибкая структура содержащая указатель и длину, которая никак не управляет и не проверяет владение фактическим буфером, за время жизни буфера и содержимое продолжает отвечать программист. Ровно подобное тривиально написать руками, но тут оно наконец стандартизировано чтоб спокойно между проектами передавать.

И как раз современная - появилась в с++17, в роли наименьшего удобного для всех случаев подмножества уровня абстракции, для тех случаев когда нужна строка, но не такая как std::string (который имеет много минусов, хотя и никакого vtbl в нём в помине нет).

GPFault ★★★
()
Ответ на: комментарий от ugoday

ожидаемое поведение

«есть только один интуитивно понятный интерфейс...». Но я не про это, а про возможные проблемы переноса этого строкового switch case на компилятор, который это не понимает и нужна куча if else.

Ну, и опять, непонятно что хуже, падение программы по null pointer dereference на strcmp() в случае if else или обработка без проверки NULL-указателя по default ветке в switch case.

mky ★★★★★
()
Ответ на: комментарий от GPFault

Это примерно то же самое что и std::basic_string, только указатель на саму строку можно свой подсунуть.

Зачем вообще для этого понадобился новый класс - я вообще не понимаю, и, наверно никогда не пойму.

Это максимально простая, понятная

Мне вот совершенно непонятно, зачем надо было копировать std::basic_string если в нём и так есть и указатель и длина. Что мешало просто добавить в std::string возможность подсовывать свой указатель?

Stanson ★★★★★
()
Ответ на: комментарий от shdown

А, ну понятно.

Дизассемблер в руки и смотреть что на самом деле происходит.

«указатель+длина» у него там. Ага. :)

Stanson ★★★★★
()
Ответ на: комментарий от mky

переноса этого строкового switch case на компилятор, который это не понимает и нужна куча if else.

Решается добавлением ещё одного if, не?

обработка без проверки NULL-указателя по default ветке в switch case.

Смысл конструкции в том, что если в строке лежит определённое значение, то выполняется определённая ветка. А если не одно из представленных значений не подошло, то использовать default. Null очевидно нетождественнен case значениям. Значит исполняется defaultовая ветка. Всё логично, хорошо и правильно.

ugoday ★★★★★
()
Ответ на: комментарий от Stanson

В.Пелевин «Священная книга оборотня».

Что Пелевин - блевотное говно было понятно еще и с его книги «Принц Госплана», которую я еще в 90-х имел неосторожность прочитать, с тех пор мнение о нем только укрепилось.

anonymous
()
Ответ на: комментарий от Stanson

Там указатель на vtable, чел.

Чтобы был указатель, надо чтобы vtable где-то была, разве не так?

vtable живёт внутри libstdc++. Если ты с ней линкуешься, vtable у тебя бесплатно будет.

С другой стороны, я вот не вижу у basic_string виртуальных функций. А значит никакого vtable там нет.

yorshka
() автор топика
Ответ на: комментарий от Stanson

У std::string, как и std::vector, std::map и прочих контейнеров нет виртуальных методов (у их итераторов тоже), а следовательно и vtable. Большая часть полиморфизма в STL статическая на шаблонах. Динамический полиморфизм используется очень ограниченно - исключения, потоки ввода-вывода и ещё по мелочи. Короче, и так тормозные вещи, которые косвенным вызовом сложно испортить.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 5)
Ответ на: комментарий от Stanson

Что мешало просто добавить в std::string возможность подсовывать свой указатель?

То что существующий std::string имеет соглашение о том что «существование объекта гарантирует валидность выделенной памяти». Как «умный указатель».

string_view по отношению к string - это как простой указатель по отношению к умному. Но умный указатель, это часто слишком большой/тяжеловесный уровень абстракции, и хочется использовать простой. Попытка создать сверх-умные указатели заменяющие всё на все случаи в том числе и простые указатели - бывает - см. библилотеки Qt и OpenCV, естестенно получается не очень. Отсюда и для строк - вместо «умного» string - появляется альтернатива использовать простой string_view.

Зачем вообще для этого понадобился новый класс - я вообще не понимаю, и, наверно никогда не пойму.

string_view это предлагаемое C++-программистам соглашение о том, как передавать строки в функции. Грубо говоря, можно передавать строки как char* или как два аргумента char* и длина. Это устоявшийся подход, у него есть свои плюсы и минусы.

Страуструп в 90х подумал «сейчас сделаю std::string, и в подавляющем большинстве случаев будет удобней чем варианты с char* и это станет новым наиболее распространённым соглашением».

Практика показала что это вовсе не всегда удобно, и теперь вперемешку применяются оба соглашения и std::string и char* с опциональным размером. Время назад не откатить, и сильно переделывать уже объявленное соглашение о поведении std::string затруднительно. Поэтому в 10х годах комитет подумал, учёл некоторые ошибки и предпринял новую попытку сделать соглашение о передачи строк в функции, которое будет удобней чем 2 предыдущих. Отсюда и появился string_view - новая итерация соглашения, не ломающая старый код.

Мой основной посыл в том - что string_view пример удачно сбалансированного уровня абстракции для класса строки в языке среднего уровня. То что добавление ещё одной сущности в C++ делает язык вцелом когнитивно сложнее (а он уже чрезмерен) - спору нет.

GPFault ★★★
()
Ответ на: комментарий от shdown

Я почему-то считал вас более компетентным.

Зря. Он как-то хвастался примерами своего офигенного кода тут, так мы там быстро за 5 минут нашли переполнение буфера на стеке. И вот так как минимум половина сишников.

Но вообще, он не то чтобы сильно неправ. 16 байт для string_view и 24 байта для string – это достаточно жирный оверхед для коротких строчек. И это накапливается, когда их много.

yorshka
() автор топика
Ответ на: комментарий от ugoday

добавлением ещё одного if

Если про это не забыть. Но мы же про реальных людей, а не про идеальных программистов, не?

Null очевидно нетождественнен case значениям.

Кому-то очевидно, а кому-то NULL вместо валидного указателя значит ошибка в коде и он вобще не должен выполняться, а не уходить по default-ветке.

Всё логично, хорошо и правильно.

Хорошо там в вашем мире розовых поней, а тут у нас всё криво, глючно и кое-как работает...

mky ★★★★★
()
Ответ на: комментарий от mky

Если про это не забыть.

Так это ж компилятор должен сделать. Или я не понял вашу мысль.

Кому-то очевидно, а кому-то NULL

Сишка, конечно, по мозгам бьёт знатно, но тут уж я не знаю чем помочь. Курить формальную логику до просветления разве.

всё криво, глючно и кое-как работает

Может быть нужно что-то исправить?

ugoday ★★★★★
()
Ответ на: комментарий от shdown

Молодец. А теперь поищи сколько все методы и используемые ими прочие классы занимают.

А потом объячни, зачем софтине в которой разок понадобилось что-то сделать с ASCIIZ строкой таскать это всё с собой?

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Дизассемблер в руки и смотреть что на самом деле происходит.

«указатель+длина» у него там. Ага. :)

Там нет никаких аллокаторов/локалей/виртуальных таблиц и других минусов тяжёлых С++ классов.

Единственное что есть «неожиданного» для неискушённого читателя - это в коде при конструировании из ASCIIZ вызов strlen записан как _Traits::length. Не-олдскульно, но сделано для поддержки wchar и подобного [наличие которого тоже уже увы не вернуть назад]. В ассемблере накладных расходов на это нет, так как для char это по шаблону заменится на strlen.

https://github.com/gcc-mirror/gcc/blob/releases/gcc-16/libstdc%2B%2B-v3/include/std/string_view#L601


  template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
    class basic_string_view
    {
      // куча методов по 3-10 строк для "синтаксического сахара", часть вкусовщина, но те что не нравятся - просто не вызываю
    private:
      size_t	    _M_len;
      const _CharT* _M_str;
    };
GPFault ★★★
()
Ответ на: комментарий от Stanson

не-в-дебаге 100% методов string-view инлайнятся ибо тривиальные, за исключением вызовов strlen и подобных. Так что накладные расходы ровно такие же нулевые как при написании этого вручную. В дебаге - вообще весь С++ однин большой накладоной расход из-за лютой влоенности тривиальных вызовов))

GPFault ★★★
()
Последнее исправление: GPFault (всего исправлений: 1)
Ответ на: комментарий от Stanson

Какие методы, наркоман, оно шаблонное и полностью в заголовочном файле содержится.

$ cat foo.cpp
#include <stdio.h>
#include <stddef.h>

#if POINTER_AND_LENGTH
struct pointer_and_length
{
    const char *my_ptr;
    size_t my_len;

    size_t size() const { return my_len; }
    const char *data() const { return my_ptr; }
};
using SPAN_TYPE = pointer_and_length;

#elif STD_STRING_VIEW

#include <string_view>
using SPAN_TYPE = std::string_view;

#endif

int main()
{
    const char *literal = "Hello";

    SPAN_TYPE s{literal, 5};

    printf("s = '%.*s'\n", (int) (s.size() < 1024 ? s.size() : 1024), s.data());

    return 0;
}
$ g++ -DPOINTER_AND_LENGTH=1 -s -static -Wall -Wextra -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections foo.cpp; du -ak ./a.out
672	./a.out
$ g++ -DSTD_STRING_VIEW=1 -s -static -Wall -Wextra -O3 -ffunction-sections -fdata-sections -Wl,--gc-sections foo.cpp; du -ak ./a.out
672	./a.out
shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от yorshka

16 байт для string_view и 24 байта для string – это достаточно жирный оверхед для коротких строчек. И это накапливается, когда их много.

… как и 8 байт для char* - тоже болшой оверхед в каких-то ситуациях)) Но string_view в силу того что не использует аллокатор - при инлайнинге может вообще выкинуть длину или указатель если в какой-то функции оно не нужно. Если говорить о хранении большого колчисетва строк (которые например находятся в memory-mapped памяти поэтому сами данные очень компактны) - тут оценивать надо да, 16 байт string_view если часто нужна длина, 8 байт char* если нет, или вообще 4 байта индекса если хранилище не более 32ГБ а начала строки выровнены по 8 байтам.

GPFault ★★★
()
Ответ на: комментарий от GPFault

«существование объекта гарантирует валидность выделенной памяти»

Если памяти выделено (занято) 0 - объект ведь не становится невалидным.

Поэтому в 10х годах комитет подумал, учёл некоторые ошибки и предпринял новую попытку сделать соглашение о передачи строк в функции, которое будет удобней чем 2 предыдущих.

Смотри - std::string - не очень удобен и вообще такое себе. В чём проблема во-первых, сделать его удобнее, а во-вторых добавить нужные фичи, вместо того, чтобы плодить новые сущности в и без того распухшем языке?

В итоге, получается что чтобы пользоваться string надо его наследовать и дописать что-то своё. Теперь надо будет ещё и string_view наследовать и писать что-то своё. Ну или писать свой класс который совместит string и string_view. В итоге получаем жирноту жирноты чисто ради работы со строками.

При этом, вся эта красота не решает, например, проблемы с освобождением изначального буфера, который посредством string_view превратили в подобие string и, возможно, расплодили в виде приватных _M_ptr, за которыми тупо сложнее уследить, например. Значит без наследования и специального аллокатора-деаллокатора всё равно не обойтись.

Для древнего и вполне серьёзного языка это всё как-то уж очень странно выглядит. Не только усложнение, но и внесение потенциальных проблем, вместо того, чтобы просто принять ASCIIZ строки как данность и неотъемлемую часть языка и не извращаться с попытками натянуть старую сову на новый глобус.

Stanson ★★★★★
()
Ответ на: комментарий от shdown

Теперь расскажи мне, зачем тогда вообще string_view, если никаких отличий нету, и функций этого string_view никто не использует? :)

Т.е. я делаю из буфера со строкой string_view, а потом тупо достаю из string_view указатель на буфер и ковыряюсь в нём сам. Зачем тогда вообще нужен string_view? :)

Stanson ★★★★★
()
Ответ на: комментарий от ugoday

что-то исправить

«работает – не трожь!» — заповеди сисадмина :)

вашу мысль

Мысль была в том, что разом во все комплияторы этот строковый switch не попадёт. Будет код, написаный с этим switch и будет ручной перенос этого кода под «старый» компилятор. И там будет ловушка, что не забудь добавить проверку на NULL перед кучей if (streq()), хотя в коде со switch case этой проверки нет.

формальную логику

Начала на Си распространять логику? Начните уж с определения поведения функций сравнения строк для NULL-указателя.

mky ★★★★★
()
Ответ на: комментарий от GPFault

Т.е. мы сделали весь из себя класс, типа для строк, загнали туда строку «Привет мир!». Хорошо. А потом оказывается, что посчитать количество символов (не байт) в строке затруднительно, потому что это юникод.

Ну и нахрена такой класс для строк в буфере? Что он даёт? Зачем он?

Придётся наследовать и дописывать этот класс. С аллокаторами-деаллокаторами, счётчиками копий, виртуальными методами и всё такое.

И наш скромный буфер с «Привет мир!» будет таскать с собой вот это вот всё.

string_view - это ещё один неюзабельный сферический конь в вакууме, которых и так в цепепе уже выше крыши. Никаких проблем не решает, только создаёт новые.

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Т.е. мы сделали весь из себя класс, типа для строк, загнали туда строку «Привет мир!». Хорошо. А потом оказывается, что посчитать количество символов (не байт) в строке затруднительно, потому что это юникод.

string_view намеренно сделан минимальным. Легковесная замена char*, которая не обязывает с собой таскать тяжёлые вещи.

Поэтому если оказывается что нужна функция подсчёта юникодных символов - то… делается то же что и ASСIIZ - она и вызывается. Никакой новый метод не пишется, ничего не наследуется. string_view это по сути plain-old-data, а НЕ вундер-вафля, его соглашение подразумевает что если нужен asciiz для внешней функции аналога которой нет в string_view - то просто передавай его, без всякого стеснения. my_external_lib_symbol_counting_func(sview.data())

При этом в большинстве даже сишных библиотек - у методов работы со строками есть аргумент длина или вариация его принимающая - и будет удобно вызвать my_external_lib_symbol_counting_func_with_len(sview.data(), sview.size()) а не вспоминать в какой переменной длина этой строки.

GPFault ★★★
()
Последнее исправление: GPFault (всего исправлений: 3)
Ответ на: комментарий от Stanson

Теперь расскажи мне

Нет, это ты расскажи, почему ты рассказывал какую-то ерунду про методы и про то, что там не только указатель и длина.

P.S. И где у std::string vtable? Там же нет виртуальных методов.

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от Stanson

Т.е. мы сделали весь из себя класс, типа для строк, загнали туда строку «Привет мир!». Хорошо. А потом оказывается, что посчитать количество символов (не байт) в строке затруднительно, потому что это юникод.

Придётся наследовать и дописывать этот класс. С аллокаторами-деаллокаторами, счётчиками копий, виртуальными методами и всё такое.

Как наследование, аллокаторы-деаллокаторы, счётчики копий, виртуальные методы помогут тебе посчитать количество «символов (не байт)»?

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от yorshka

24 байта для string

Справедливости ради, sizeof(std::string) = 32. Вроде бы это SSO. Я думал, что её запретили в C++11, но нет, запретили CoW.

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 2)
Ответ на: комментарий от GPFault

string_view намеренно сделан минимальным. Легковесная замена char*, которая не обязывает с собой таскать тяжёлые вещи.

Зачем он тогда нужен вообще? Зачем char* на что-то заменять, если никаких плюшек нету.

то… делается то же что и ASСIIZ - она и вызывается. Никакой новый метод не пишется, ничего не наследуется. string_view это по сути plain-old-data

Но зачем тогда это всё, если один хрен придётся работать с ASCIIZ?

будет удобно вызвать my_external_lib_symbol_counting_func_with_len(sview.data(), sview.size()) а не вспоминать в какой переменной длина этой строки.

Весьма сомнительное преимущество. Никто же не мешает сделать

char* swview_data = "Привет мир!";
size_t swview_size = strlen(swview_data);
...

my_external_lib_symbol_counting_func_with_len(sview_data, sview_size)

Т.е. никаких новых плюшек вообще.

Если уж делать новую строку на замену char*, то это не какой-нибудь класс должен быть, а новый базовый тип данных, типа double/float например, где в 8/4 байтах хранятся аж три разных параметра - «знак», «порядок» и «мантисса». Так же и базовый тип данных «строка» вполне может хранить параметры «длина» и «содержимое» в одном типе, без всяких структур, классов и пр. Соответственно и всякие указатели, индексы и пр. при применении к строке должны работать на уровне базового типа, а не каких-либо библиотечных функций. Как оно внутри компилятора будет выглядеть - дело десятое, главное чтобы этот тип был базовой частью языка, как int, float и пр., а не каким-то костылём.

Но, разумеется, это намного сложнее чем выдумывать новые классы в библиотечке.

Так что никуда строки ASCIIZ со всем их недостатками не денутся, а все эти «нормальные» строки так и останутся костылями.

Stanson ★★★★★
()
Ответ на: комментарий от shdown

Я конечно не эксперт, но basic_string в конструкторе имеет параметр аллокатор, если он не стандартный, свой кастомнный, то где-то его надо сохранить. Возможно есть специализация оптимизация для стандартного аллокатора

anonymous
()
Ответ на: комментарий от shdown

Как наследование, аллокаторы-деаллокаторы, счётчики копий, виртуальные методы помогут тебе посчитать количество «символов (не байт)»?

Ну как минимум, чтобы у строки появился метод считающий количество символов придётся создать новый класс наследуя этот самый string_view. Надо где-то будет хранить кодировку, чтобы считалка работала. Опять без наследования никак. Виртуальный метод понадобится чтобы какой-нибудь sview.symbols() менять в зависимости от кодировки, при смене кодировки может понадобится побольше памяти под строку, придётся аллокатор делать, т.к. у нас ссылка на буфер со стороны, надо следить, когда ему free() сделают, ну и т.п.

Мы ж «строку» делаем, «правильную», а не костыли какие-то недоделанные, не так ли?

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Ну как минимум, чтобы у строки появился метод считающий количество символов придётся создать новый класс наследуя этот самый string_view.

Зачем? Если мы храним байты, то это будет просто функция. Если ты хочешь, чтобы символы изначально хранились в wchar_t, то для этого есть std::wstring_view (aka std::basic_string_view<wchar_t>).

Надо где-то будет хранить кодировку, чтобы считалка работала

Она вообще-то в локали хранится. Той самой, которая меняется с помощью setlocale(). Можешь, конечно, свой велосипед написать, но зачем?

Виртуальный метод понадобится чтобы какой-нибудь sview.symbols() менять в зависимости от кодировки, при смене кодировки может понадобится побольше памяти под строку

Так у нас для каждой кодировки новый дочерний класс или она глобальная и можно организовать её «смену» на ходу?

при смене кодировки может понадобится побольше памяти под строку

Так ты ж говорил, что там просто байты лежат!

придётся аллокатор делать, т.к. у нас ссылка на буфер со стороны, надо следить, когда ему free() сделают, ну и т.п.

Всё, какая-то шизофазия пошла.

Мы ж «строку» делаем, «правильную», а не костыли какие-то недоделанные, не так ли?

Кто «мы»-то, ты один тут какую-то ерунду пишешь.

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от shdown

Если мы храним байты

то нам никакой string_view вообще не нужен. :)

Она вообще-то в локали хранится. Той самой, которая меняется с помощью setlocale()

Вот только далеко не факт, что в нашем буфере окажется именно такая кодировка.

Так у нас для каждой кодировки новый дочерний класс или она глобальная и можно организовать её «смену» на ходу?

Кодировка - это неотъемлемый параметр абстрактной «строки», вообще-то. Такой же как длина, например.

Так ты ж говорил, что там просто байты лежат!

Ну это для меня, сишника заядлого, байты. А тут речь о «правильной строке».

Всё, какая-то шизофазия пошла.

Шизофазия - это придумывать какие-то костыли, называть их «правильными строками» и мечтать о замене ASCIIZ на это.

Кто «мы»-то, ты один тут какую-то ерунду пишешь.

Меня ASCIIZ устраивает целиком и полностью, и я вообще не вижу никаких проблем с ней. Я всего лишь пытаюсь поставить себя на место этих искателей «правильных строк». Как видишь, херня какая-то выходит.

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Покажи мне хоть один проект, где попытались изобрести «правильную строку». Ну вот просто правильную, без оговорок про конкретную цель.

Конкретно под то, что ты описываешь (зачем это нужно-то?) сделай себе

struct Encoding_KOI8R
{
    using Symbol = uint8_t;
    static size_t count_graphemes(std::basic_string_view<Symbol> s) { return s.size(); }
};
struct Encoding_UTF32
{
    using Symbol = uint32_t;
    static size_t count_graphemes(std::basic_string_view<Symbol> s) { /* ... */ }
};
struct Encoding_UTF8
{
    using Symbol = uint8_t;
    static size_t count_graphemes(std::basic_string_view<Symbol> s) { /* ... */ }
};
И сделай template<class Encoding> class OrthodoxString { ... };. Никаких наследований, аллокаторов, виртуальных методов, счётчиков копий для этого не нужно.

Шизофазия - это придумывать какие-то костыли, называть их «правильными строками» и мечтать о замене ASCIIZ на это.

Именно этим ты и занимаешься, только не мечтая о замене ASCIIZ на это, а мечтая доказать с помощью straw man, что не нужно заменять ASCIIZ на это.

shdown ★★
()
Ответ на: комментарий от Stanson

Меня ASCIIZ устраивает целиком и полностью, и я вообще не вижу никаких проблем с ней

Нравится длину на каждый чих пересчитывать? Да, я тоже не люблю, когда проц простаивает. И зимой тепло!

yorshka
() автор топика
Ответ на: комментарий от shdown

Это какой-то экспериментальный шланг.

Это тот, который был в твоём примере выше про string_view. Я туда сунул string ради интереса и тоже удивился, увидев 24.

yorshka
() автор топика
Ответ на: комментарий от shdown

сделай себе

Это если заранее знаешь, что у тебя будет в буфере объекта. А если там то UTF-8, то CP1251, тo виндовый WCHAR, то UTF-32 приезжает? Что получается если забить на такой важный параметр строки как кодировка, которая может быть оказаться любой? А вон, например, до сих пор проблема IDv3 тегов в mp3 не решена, нет-нет, да вылезают кракозябры. И нет, не только на русском. Забили на один из важных параметров «правильной строки» - и вот геморрой на десятилетия. Толку от того, что длина там хранится.

Да и мне-то не нужна эта «правильная строка», меня ASCIIZ более чем устраивает. Вот чтобы в switch ASCIIZ строки можно было бы использовать - это не помешало бы, да. Какой-то код можно было бы написать покрасивше. Только хрен дождёшся, скорее switch опять поломают. А к самим ASCIIZ строкам претензий нет никаких.

Я пытаюсь представить как может выглядеть «правильная строка», чтобы ею можно было пользоваться просто и приятно без костылей и дописывания чего-либо. Ладно, пусть только в цепепе. Ну и получается что «правильная строка» кроме как раздутой жирнотой быть в принипе не может.

Так зачем тогда вообще менять ASCIIZ на что-то недоделанное и неудобное? Откуда взялось это желание поменять ASCIIZ на что-то другое, и что на самом деле хотят эти ждуны?

Stanson ★★★★★
()
Ответ на: комментарий от mky

«работает – не трожь!»

Хреново работает.

Будет код, написаный с этим switch и будет ручной перенос этого кода под «старый» компилятор.

А в чём разница с переносом кода между стандартами? Договариваешься на берегу «пишем под С89 или С23» и вперёд.

Начала на Си распространять логику?

Пора бы уже.

Начните уж с определения поведения функций сравнения строк для NULL-указателя.

Давайте вместе подумаем над силлогизмом.

Посылка раз: если строка содержит значение «мама» нужно вызывать foo(), иначе bar().

Посылка два: NULL не является значением «мама».

Вывод: ????

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Давайте вместе подумаем над силлогизмом.

Посылка раз: если строка содержит значение «мама» нужно вызывать foo(), иначе bar().

Посылка два: NULL не является значением «мама».

Вывод: ????

Посылка раз: если строка содержит значение «мама» нужно вызывать foo(), иначе bar().

Посылка два: MAP_FAILED ((void *)-1) не является значением «мама».

Вывод: ????

shdown ★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.