Здравствуйте, alex_public, Вы писали:
_> Но насколько я знаю в C++14 ничего принципиального не ожидается, скорее так, косметика...
На сколько я знаю, в C++14 и не планировали вводить много языковых фич, но тем не менее будут концепции и п.лямбда.
EP>>В C++11 можно (гугли "Using strings in C++ template metaprograms", + должно уже быть в библиотеках) _>Это ты про жуть типа задания отдельными буквами или про что? )
Нет конечно — "отдельными буквами" это доступно и в C++98. Строки с виду вполне обычные: MPLLIBS_STRING("hello")
Там даже как proof-of-concept делали compile-time разбор regexp в дерево Boost.Xpressive.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>std::vector — тоже range.
Он гораздо большее)
EP>А что произойдёт, если допустим slice'у от массива попытаться увеличить размер?
Оно заживёт самостоятельной жизнью (данные скопируются в новую область).
EP>partition_point делает бинарный поиск — поэтому ему нужен ForwardRange как минимум.
Тьфу, я в этих названия у них путаюсь. Собственно я ещё ни разу не использовал range в D, хотя уже много чего делали...
EP>Даже в том коде были разнообразные проблемы, как с гибкостью, так и с производительностью. EP>А в случае partition_point ещё и реализация будет неудобная. AFAIK в D есть бинарный поиск только для RandomAccess, в то время как в STL он спокойно работает и для ForwardIterator.
А что там неудобного? Насколько я помню нормальный код.
Здравствуйте, alex_public, Вы писали:
EP>>А что произойдёт, если допустим slice'у от массива попытаться увеличить размер? _>Оно заживёт самостоятельной жизнью (данные скопируются в новую область).
А какие типы будут у: массива, массива после slice, массива после slice и resize?
Если одинаковые, то получается оверхед на хранение own_flag, и его постоянную проверку.
EP>>partition_point делает бинарный поиск — поэтому ему нужен ForwardRange как минимум. _>Тьфу, я в этих названия у них путаюсь.
Ну пусть будет std::lower_bound — практически тоже самое.
EP>>Даже в том коде были разнообразные проблемы, как с гибкостью, так и с производительностью. EP>>А в случае partition_point ещё и реализация будет неудобная. AFAIK в D есть бинарный поиск только для RandomAccess, в то время как в STL он спокойно работает и для ForwardIterator. _>А что там неудобного? Насколько я помню нормальный код.
В STL как раз нормальный. А в D, хоть и делали с оглядкой на STL — бинарный поиск, afaik, только для RandomAccess.
Ну или другой пример — есть строка UTF-8, по ней нужно бегать туда-сюда. На BidirectionalIterator — это делается влёт.
А на D BidirectionalRange — нет, так как такие range только уменьшаются, но не растут обратно.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>А какие типы будут у: массива, массива после slice, массива после slice и resize? EP>Если одинаковые, то получается оверхед на хранение own_flag, и его постоянную проверку.
Одинаковые. Добавление данных к слайсу действительно имеет некоторый оверхед. Если нужно много данных добавлять подряд, есть быстрый std.array.Appender.
Здравствуйте, D. Mon, Вы писали:
EP>>А какие типы будут у: массива, массива после slice, массива после slice и resize? EP>>Если одинаковые, то получается оверхед на хранение own_flag, и его постоянную проверку. DM>Одинаковые. Добавление данных к слайсу действительно имеет некоторый оверхед.
Хотя я думаю в случае с resize, при использовании GC, можно обойтись без overhead'а: у slice'а автоматом capacity устанавливается равной .size() — тогда дополнительные проверки не нужны.
Но как, например, разгуливается ситуация с popBack? Если у нас "оригинальный" массив — то нужно позвать деструктор (либо сообщить GC — занулить указатель), а если slice — то нужно только сдвинуть указатель/уменьшить size.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Но как, например, разгуливается ситуация с popBack? Если у нас "оригинальный" массив — то нужно позвать деструктор (либо сообщить GC — занулить указатель), а если slice — то нужно только сдвинуть указатель/уменьшить size.
Просто уменьшается длина слайса. Данные не освобождаются и не обнуляются сразу, это отдается на откуп GC. Пока хоть один слайс ссылается на исходный массив, все его данные будут в памяти. (тут как со строками в джаве до 1.7) Можно, конечно, вручную подчистить, если уверен, что на них точно нет других ссылок, но это считается небезопасным и неидиоматичным, однако вполне доступно.
Здравствуйте, D. Mon, Вы писали:
EP>>Но как, например, разгуливается ситуация с popBack? Если у нас "оригинальный" массив — то нужно позвать деструктор (либо сообщить GC — занулить указатель), а если slice — то нужно только сдвинуть указатель/уменьшить size. DM>Просто уменьшается длина слайса. Данные не освобождаются и не обнуляются сразу, это отдается на откуп GC.
Это понятно, а что происходит когда оригинальный массив без всяких slice'ов делает popBack? Он тоже не зануляет/не деструктит?
То есть что происходит в такой ситуации:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Это понятно, а что происходит когда оригинальный массив без всяких slice'ов делает popBack? Он тоже не зануляет/не деструктит?
Да. У него и нет никакого pop_back, а есть изменяемая length. Если ее уменьшить на 1, это эквивалентно взятию слайса
v = v[0..$-1];
Если нужно детерминированное освобождение ресурсов при этом, то простой массив не годится, нужна обертка над ним с соответствующей логикой.
Здравствуйте, D. Mon, Вы писали:
EP>>Это понятно, а что происходит когда оригинальный массив без всяких slice'ов делает popBack? Он тоже не зануляет/не деструктит? DM>Если нужно детерминированное освобождение ресурсов при этом, то простой массив не годится, нужна обертка над ним с соответствующей логикой.
Здравствуйте, minorlogic, Вы писали:
EP>>Взять например те же ranges — они проигрывают итераторам по производительности by-design M>Этого не понял , ranges же легко делать поверх итераторов , где там производительность потеряется ?
Ranges действительно легко делать поверх итераторов — например Boost.Range. Но в D нет итераторов — там сразу Range.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>А какие типы будут у: массива, массива после slice, массива после slice и resize? EP>Если одинаковые, то получается оверхед на хранение own_flag, и его постоянную проверку.
Ну я же говорил, что оно хотя и похоже на std::vector, но со специфическими свойствами владения. Т.е. кроме того, что не освобождает память в деструкторе, оно ещё и в операторе присваивания копирует только указатель. Соответственно раз у нас даже просто копии массива являются по своей сути ссылками на чужие данные, то понятно что уж срезы то точно именно через это и реализуют.
Т.е. изменение элементов как просто копий массива, так и срезов, затрагивает изначальные данные. А вот операция добавления элемента в массив порождает новую область памяти, в которую копируется старая и новый элемент. Ну и естественно у каждого массива есть метод dup, порождающий новую реальную копию данных.
Вообще говоря при изучение этого я бы не сказал что оно вот так прямо интуитивно реализовано. Однако на практике пользоваться довольно удобно.
EP>В STL как раз нормальный. А в D, хоть и делали с оглядкой на STL — бинарный поиск, afaik, только для RandomAccess.
EP>Ну или другой пример — есть строка UTF-8, по ней нужно бегать туда-сюда. На BidirectionalIterator — это делается влёт. EP>А на D BidirectionalRange — нет, так как такие range только уменьшаются, но не растут обратно.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Нашёл — нужен std.container.Array
Ага. А ещё массив из D фиксированного размера имеет поведение уже не как странный std::vector, а как std::array, т.е. по сути как массив C++. Т.е. выделение на стеке и соответственно гарантированное освобождение.
Здравствуйте, alex_public, Вы писали:
_>Ага. А ещё массив из D фиксированного размера имеет поведение уже не как странный std::vector, а как std::array, т.е. по сути как массив C++.
Что значит "странный std::vector"?
EP>>Ну или другой пример — есть строка UTF-8, по ней нужно бегать туда-сюда. На BidirectionalIterator — это делается влёт. EP>>А на D BidirectionalRange — нет, так как такие range только уменьшаются, но не растут обратно. _>Так там же save есть у большинства диапазонов.
BidirectionalRange это по сути два Forward итератора бегущих друг на встречу другу, а для нормальной обработки UTF-8 нужен Bidirectional Iterator. И .save() тут никак не поможет (точнее может, но это будут дополнительные расходы в виде временных буферов).
Например простейший случай: найти заданный символ в строке, и вывести N предыдущих в обратном порядке.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Что значит "странный std::vector"?
Да это я всё про то, что массивы D — это std::vector, но извращённый. )))
EP>BidirectionalRange это по сути два Forward итератора бегущих друг на встречу другу, а для нормальной обработки UTF-8 нужен Bidirectional Iterator. И .save() тут никак не поможет (точнее может, но это будут дополнительные расходы в виде временных буферов). EP>Например простейший случай: найти заданный символ в строке, и вывести N предыдущих в обратном порядке.
Аааа теперь понял про что ты. Ну да, собственно BidirectionalRange — это вообще странная конструкция. ))) А DList из стандартной библиотеки (заточенный под эту хрень) соответственно не умеет такую очевидную вещь, как "получить предыдущий элемент" — ужас. )))
Но это именно BidirectionalRange, а вот если у нас RandomAccessRange (кстати, строки то как раз почти всегда или такие или InputRange), то наоборот всё становится очень и очень удобно.
Здравствуйте, alex_public, Вы писали:
_>Но это именно BidirectionalRange, а вот если у нас RandomAccessRange (кстати, строки то как раз почти всегда или такие или InputRange), то наоборот всё становится очень и очень удобно.
Для UTF-8 строк нет random access без дополнительного расхода памяти, а вот bidirectional — есть (например boost::u8_to_u32_iterator).
RandomAccessRange по сравнению с итераторами как-то тоже не айс:
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Для UTF-8 строк нет random access без дополнительного расхода памяти, а вот bidirectional — есть (например boost::u8_to_u32_iterator).
Ну так это ты про итерацию уже по символам, а на нижнем уровне то массив байт обычно.
Кстати, если говорить конкретно про utf(8, 16, 32), то в D это всё встроено прямо в язык. Т.е. можно написать так:
string str="Привет";//str - массив байт со строкой utf-8foreach(c; str) writeln(c);//выведет хреньforeach(dchar c; str) writeln(c);//выведет корректно по буквам
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>Нашёл — нужен std.container.Array
_>Ага. А ещё массив из D фиксированного размера имеет поведение уже не как странный std::vector
Здравствуйте, DarkEld3r, Вы писали: DE>Лол что? Ни с чем не перепутал? Вообще-то Линус категорически не любит С++.
Линус кроме ядра линукса и гита ничем не занимается, в принципе.
А вот всякие гномы и кеды и остальные из мира опенсорса сделаны на инкрементированных сях.