Как стать автором
Обновить
27
0

Пользователь

Отправить сообщение
Удобная сериализация данных с Variadic Templates
А я не понял, в чем, собственно, удобство? Чем это решение лучше, чем просто операторы << и >> с каким-нибудь специальным классом, представляющим поток сериализованных данных?

При таком подходе не нужно наследование и не нужен метод SerializedSize. Способ представления сериализованных данных зависит от класса потока, соответственно, не только легко можно подменить одну реализацию другой, но и иметь несколько различных реализаций потоков одновременно. А кроме того, это будет работать без variadic template-ов, а разница в использовании сведется к замене "," в вызове функции на << или >>.
Компилятор выдает ошибку
Ошибку выдает компоновщик, т. е. вы сначала 2 часа будете ждать пока все скомпилируется, а потом, при компоновке, вам сообщат, что вы оказывается «обратились к приватной функции» (причем шифрованным сообщением) и зря ждали 2 часа пока все скомпилируется.

Тем не менее, оставить один указатель лучше, чем хранить все данные в паблик структуре.
Не очевидное утверждение, особенно, на таком примере, в котором вы тут же в дополнение к закрытым данным делаете set и get с тривиальной функциональностью, это явно не лучше, чем просто оставить x и y доступными снаружи.

Кроме того, инкапсуляция может осуществляется как соглашение между программистами без всякой поддержки со стороны компилятора. Например, все поля, имена которых начинаются с нижнего подчеркивания лучше не трогать снаружи какого-то модуля, а если уж трогаете, то на свой страх и риск.
Да, вы правы, поправил.
Факториал все еще не факториал, а арифметическая прогрессия по сути просто умножение двух чисел, это конечно тоже арифметическая прогрессия, но пример не показательный, того же эффекта можно достигнуть просто перемножив числа.
Мы получаем наследуемые inline методы с полиморфным поведением!
Вы так подчеркиваете, то что они inline, это существенно?
Существенно то, что компилятор сделает их встроенными
Переформулирую вопрос, а почему это существенно? Если вы думаете, что он подставит их тело вместо вызова, то он этого может и не сделать.
Смотрим… Работает!

Вообще-то не работает.

Получаем некорректный результат, и ни одного предупреждения

А какие предупреждения вы ожидали? О переполнении? Но тогда даже без шаблонов вы его вряд ли увидите.

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

Мы получаем наследуемые inline методы с полиморфным поведением!

Вы так подчеркиваете, то что они inline, это существенно? Кстати, в данном случае inline писать совсем не обязательно, потому что функции определенные внутри класса автоматически являются inline.
Туплю, там конечно же хвостовая рекурсия, так что я не прав.
А как вы реализуете поиск медианы без рекурсии и дополнительной памяти?
В QuickSort вы не выбираете размеры подмасивов, вы выбираете опорный элемент, а в зависимости от опорного элемента получаются разные размеры подмасивов, так что ваша стройная теория о делении пополам не работает.
Имелось в виду массивное распаралливание на GPU, насколько знаю такого нет.

ок, я неправильно понял фразу в первом параграфе.
не требут дополнительной памяти.

если вы не используете какую-то экзотическую версию QuickSort, то вы не правы. Дополнительная память требуется, как минимум на стек, и в лучшем случае можно добиться, чтобы глубина не превышала log N, но так чтобы свести дополнительную память до константы в QuickSort, я бы с радостью почитал статью про это.
После прочтения статьи у меня появилось два вопроса:
  1. с чего вы взяли, что QuickSort не поддается распараллеливанию? Например, parallel_sort в intel tbb использует QuickSort;
  2. с чего вы взяли, что QuickSort не использует дополнительной памяти? Классическая рекурсивная реализация использует как минимум log N памяти;
accumulate не использует +=, вот в чем штука. Оператор поправлю, спасибо

принято, я неправ.

их никто не дает

тогда я не понимаю, к чему вы написали это:
Стандартом не гарантируется, что for_each будет оптимизирована так же хорошо, как и цикл, а это важно, если вы пишете переносимый код.
Ассемблерный код выглядит так как будто компилировали с -Os, а не с -O3. Например, вот код который сгенерировал g++ у меня (g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2) с -Os:

        movq    8(%rdi), %rdx
        movq    (%rdi), %rax
        xorl    %esi, %esi
.L2:
        cmpq    %rdx, %rax
        je      .L6
        addl    (%rax), %esi
        addq    $4, %rax
        jmp     .L2


причем он одинаковый и для for_each и для accumulate (у меня += возвращает ссылку). Код же с -O3 я приводить не буду потому что в нем развернут цикл, используются векторные инструкции и прочее, но и там версии для accumulate и for_each одинаковые.

Стандартом не гарантируется, что for_each будет оптимизирована так же хорошо, как и цикл, а это важно, если вы пишете переносимый код.

а гарантии по оптимизации циклов стандарт дает что ли?

Кстати, вам не кажется странным тот факт, что специализированная функция для подсчета суммы дает худший результат, чем цикл или использование for_each?

может дело не в accumulate, а в вашей реализации +=?
А почему вы уверены, что в строке sum += vec[i] вызывается const метод? Кажется, если сам vec не const, то из const и не const метода будет выбран как раз последний.
Нет, имеется ввиду, что i изменяется и читается в одном выражении. Например, порядок вычисления array[i] и array[++i] не определен, например, он может сначала посчитать array[++i] и тогда программа дважды обратится к одному и тому же элементу массива, что не правильно.

А вообще вот, что пишет стандарт:
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

В данном случае, как я понимаю, сайд эффект от ++i «unsequenced» с использованием i в array[i].
польза статьи, скорее всего, в том, чтобы показать необходимость знать детали «работы» языка.

Вероятно, я невнимательно прочитал, потому что я не заметил описания каких-то деталей работы языка.

иначе эта опция был бы включена по умолчанию

Я думал, что оптимизации не включены по-умолчанию, чтобы сделать отладку проще и компиляцию быстрее (gcc docs), или другими словами сделать процесс разработки более удобным, разве нет?
new (Storage.data()) Callable(std::move(Fn));


а деструктор у Callable вызывать не нужно? Кроме того, чем вам type erasure не угодил, зачем в vector-е конструировать Callable (может у меня вкус плохой, но мне конкретно этот момент не кажется элегантным решением)?
Во-первых, может потребоваться какое-то время на ответ, конкретное время зависит от подсистемы, в которую вы отправили патч. Различные исправления кодстайла, мелкие чистки кода и другие некритические изменения, часто, имеют меньший приоритет, по сравнению с исправлениями багов, так что нет ничего удивительного, что вам не отвечают сразу.
Во-вторых, перед тем как отправить патч стоило почитать правила, которым он должен удовлетворять, как минимум должен быть Signed-off-by и описание изменений. Правила описаны тут.
Число 0xffffffff-MAX_ERRNO+1 — меньше 2^32, так что не за пределами.
Наверно, стоит указать, что это перевод и дать ссылку на оригинал: duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/

Информация

В рейтинге
Не участвует
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Дата рождения
Зарегистрирован
Активность