Как стать автором
Обновить
28
0
Aleksey @kiwhy

Разработчик

Отправить сообщение

Как мы реализовали систему камер для мобильной TPS игры

Время на прочтение11 мин
Количество просмотров5.6K

Как ранее упоминали в наших статьях на Хабре, сейчас Social Quantum разрабатывает мобильный Survival Action RPG от третьего лица в зомби сеттинге. Мы поставили цель — подарить игрокам консольный фил, доступный на мобильных девайсах. Один из приемов, который для этого используем — система камер. В этой статье рассказываем, как реализовали её в Unreal Engine 4 на С++.

Читать далее
Всего голосов 14: ↑13 и ↓1+12
Комментарии7

C++ zero-cost abstractions на примере хеш-таблиц в ClickHouse. Доклад Яндекса

Время на прочтение12 мин
Количество просмотров12K
Хеш-таблицы — это королевы структур данных. Нигде не сломано так много копий, как на оптимизации хеш-таблиц. В докладе я рассказал ещё об одной хеш-таблице, которая используется в ClickHouse. Вы увидите, что zero-cost abstractions в современном С++ оправдывают себя и как с помощью небольших трюков получить разнообразные структуры данных из общей кодовой базы. На основе общих строительных блоков можно построить быстроочищаемую хеш-таблицу, несколько видов LRU-кешей, lookup-таблицы без хешей, хеш-таблицы для строк и т. п. Я показал, как получить максимальную производительность на конкретных сценариях и не ошибиться при её тестировании. В моём докладе — самая мякотка низкоуровневых оптимизаций. В общем, то, что мы любим.

— Для начала мы обсудим, зачем нужны хеш-таблицы, где их можно использовать в базах данных и как сделать их оптимальными. Затем посмотрим бенчмарки различных хеш-таблиц в интернете и разбёремся, как делать их правильно. В конце посмотрим на C++-обертку над идеальной хеш-таблицей в ClickHouse.
Читать дальше →
Всего голосов 35: ↑32 и ↓3+29
Комментарии10

Совершенный цикл for

Время на прочтение6 мин
Количество просмотров53K

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


Я довольно давно пишу код, и так вышло, что практически всегда на C++. Даже и не могу прикинуть, сколько раз я написал подобную конструкцию:


for (int i=0; i<size; i++) {
    [...]
}

Хотя почему не могу, очень даже могу:


find . \( -name \*.h -o -name \*.cpp \) -exec grep -H "for (" {} \; | wc -l
43641

Наш текущий проект содержит 43 тысячи циклов. Проект пилю не я один, но команда маленькая и проект у меня не первый (и, надеюсь, не последний), так что в качестве грубой оценки пойдёт. А насколько такая запись цикла for хороша? Ведь на самом деле, важно даже не то количество раз, когда я цикл написал, а то количество раз, когда я цикл прочитал (см. отладка и code review). А тут речь очевидно идёт уже о миллионах.


На КПДВ узел под названием «совершенная петля» (perfection loop).


image


Так каков он, совершенный цикл?

Читать дальше →
Всего голосов 92: ↑90 и ↓2+88
Комментарии172

Путь в программисты (С++)

Время на прочтение13 мин
Количество просмотров111K
Привет. С вами я. Мне нравилось боксировать и бегать на дальние дистанции, и думал я только о спорте, но выучился на моряка. Работал в авиации, а стал программистом С++ в 29. Расскажу, как так получилось.

О программировании к октябрю 2017 я знал ровно столько, сколько сейчас о квантовой физике- ничего. Абсолютно. «hello world»- даже не слышал о такой фразе. Время от начала обучения до трудоустройства — полтора года.

Почему решил расписать свое обучение?- потому что знаю по себе, как тяжело найти хорошую работу в СНГ. Мест, где есть карьерный рост, нормально оплачивается труд в инженерии и смежных областях я не встретил, везде ты просто рабочий, всем до одного места на твои амбиции, желание повысить квалификацию, как-то вырасти.

Особенно этот пост пишу с мыслями о земляках в Сибири и на Дальнем Востоке, так как там с хорошей работой тяжелее дважды, о людях с ограниченными возможностями, которые не могут жить полноценной жизнью не только из-за своих физических ограничений, но и из-за того, что у них нет возможности работать на нормальной должности и чувствовать себя уверенно в том, что завтра ты не пропадешь, ты нужен, тебя ценят. К слову, мой коллега имеет инвалидность по зрению и работает вполне успешно. Поэтому, для некоторых, я уверен, подойдет мой копи-паст учебы. Сразу опишу его, потом остальное.
Читать дальше →
Всего голосов 64: ↑58 и ↓6+52
Комментарии145

Инициализация в современном C++

Время на прочтение26 мин
Количество просмотров148K


Общеизвестно, что семантика инициализации — одна из наиболее сложных частей C++. Существует множество видов инициализации, описываемых разным синтаксисом, и все они взаимодействуют сложным и вызывающим вопросы способом. C++11 принес концепцию «универсальной инициализации». К сожалению, она привнесла еще более сложные правила, и в свою очередь, их перекрыли в C++14, C++17 и снова поменяют в C++20.


Под катом — видео и перевод доклада Тимура Домлера (Timur Doumler) с конференции C++ Russia. Тимур вначале подводит исторические итоги эволюции инициализации в С++, дает системный обзор текущего варианта правила инициализации, типичных проблем и сюрпризов, объясняет, как использовать все эти правила эффективно, и, наконец, рассказывает о свежих предложениях в стандарт, которые могут сделать семантику инициализации C++20 немного более удобной. Далее повествование — от его лица.

Всего голосов 62: ↑61 и ↓1+60
Комментарии125

Трактат о Pinе. Мысли о настройке и работе с пинами на С++ для микроконтроллеров (на примере CortexM)

Время на прочтение15 мин
Количество просмотров8.1K

Последнее время я сильно увлекся вопросом надежности софта для микроконтроллеров, 0xd34df00d посоветовал мне сильнодействующие препараты, но к сожалению руки пока не дошли до изучения Haskell и Ivory для микроконтроллеров, да и вообще до совершенно новых подходов к разработке ПО отличных от ООП. Я лишь начал очень медленно вкуривать функциональное программирование и формальные методы.


Все мои потуги в этих направлениях это, как было сказано в комментарии ради любви к технологиям, но есть подозрение, что сейчас никто не даст мне применять такие подходы (хотя, как говориться, поживем увидим). Уж больно специфические навыки должны быть у программиста, который все это дело будет поддерживать. Полагаю, что написав однажды программу на таком языке, моя контора будет долго искать человека, который сможет принять такой код, поэтому на практике для студентов и для работы я все еще по старинке использую С++.


Продолжу развивать тему о встроенном софте для небольших микроконтроллеров в устройствах для safety critical систем.


На этот раз попробую предложить способ работы с конкретными ножками микроконтроллера, используя обертку над регистрами, которую я описал в прошлой статье Безопасный доступ к полям регистров на С++ без ущерба эффективности (на примере CortexM)


Чтобы было общее представление того о чем я хочу рассказать, приведу небольшой кусок кода:


using Led1Pin = Pin<Port<GPIOA>, 5U, PinWriteableConfigurable> ;
using Led2Pin = Pin<Port<GPIOC>, 5U, PinWriteableConfigurable> ;
using Led3Pin = Pin<Port<GPIOC>, 8U, PinWriteable> ;
using Led4Pin = Pin<Port<GPIOC>, 9U, PinWriteable> ;
using ButtonPin = Pin<Port<GPIOC>, 10U, PinReadable> ;

//Этот вызов развернется в  2 строчки
// GPIOA::BSRR::Set(32) ; // reinterpret_cast<volataile uint32_t *>(0x40020018) = 32U 
// GPIOС::BSRR::Set(800) ; // reinterpret_cast<volataile uint32_t *>(0x40020818) = 800U 
 PinsPack<Led1Pin, Led2Pin, Led3Pin, Led4Pin>::Set() ; 

//Ошибка компиляции, вывод к которому подключена кнопка настроен только на вход
ButtonPin::Set() 

auto res = ButtonPin::Get() ; 
Читать дальше →
Всего голосов 11: ↑10 и ↓1+9
Комментарии181

Пишем собственный воксельный движок

Время на прочтение11 мин
Количество просмотров23K
image

Примечание: полный исходный код этого проекта выложен здесь: [source].

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

После выпуска первоначального концепта Task-Bot [перевод на Хабре] я почувствовал, что меня ограничивает двухмерное пространство, в котором я работал. Казалось, что оно сдерживает возможности емерджентного поведения ботов.

Предыдущие неудачные попытки изучения современного OpenGL поставили передо мной мысленный барьер, но в конце июля я каким-то образом наконец пробил его. Сегодня, в конце октября, у меня уже достаточно уверенное понимание концепций, поэтому я выпустил собственный простой воксельный движок, который будет средой для жизни и процветания моих Task-Bots.

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

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

Так как движок уже довольно сильно продвинулся вперёд и я снова перехожу к программированию ботов, я решил написать пост о движке, его функциях и реализации, чтобы в будущем сосредоточиться на более высокоуровневых задачах.
Всего голосов 25: ↑24 и ↓1+23
Комментарии9

Процесс компиляции программ на C++

Время на прочтение5 мин
Количество просмотров202K

Цель данной статьи:


В данной статье я хочу рассказать о том, как происходит компиляция программ, написанных на языке C++, и описать каждый этап компиляции. Я не преследую цель рассказать обо всем подробно в деталях, а только дать общее видение. Также данная статья — это необходимое введение перед следующей статьей про статические и динамические библиотеки, так как процесс компиляции крайне важен для понимания перед дальнейшим повествованием о библиотеках.

Читать дальше →
Всего голосов 44: ↑35 и ↓9+26
Комментарии29

C++ vtables. Часть 2 (Virtual Inheritance + Compiler-Generated Code)

Время на прочтение10 мин
Количество просмотров13K

Перевод статьи подготовлен специально для студентов курса «Разработчик С++». Интересно развиваться в данном направлении? Смотрите запись мастер-класса «Практика использования Google Test Framework»!



Часть 3 — Виртуальное наследование


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

Читать дальше →
Всего голосов 23: ↑23 и ↓0+23
Комментарии2

Работа со списком Pinов, на С++ для микроконтроллеров (на примере CortexM)

Время на прочтение13 мин
Количество просмотров8.3K


Всем доброго здравия!


В прошлой статье я обещал написать о том, как можно работать со списком портов.
Сразу скажу, что уже все было решено до меня аж в 2010 году, вот статья: Работа с портами ввода-вывода микроконтроллеров на Си++ . Человек написавший это в 2010 просто красавчик.


Мне было немного неловко, что я будут делать то, что уже сделано 10 лет назад, поэтому я решил не дожидаться 2020 года, а сделать это в 2019, чтобы повторить решение еще пока 9 летней давности, это будет не так стремно.


В выше указанной статье работа со списками типов была сделана с помощью C++03, когда еще шаблоны имели фиксированное число параметров, а функции не могли быть constexpr выражениями. С тех пор С++ "немного изменился", поэтому давайте попробуем сделать тоже самое, но на С++17. Добро пожаловать под кат:

Читать дальше →
Всего голосов 9: ↑7 и ↓2+5
Комментарии47

Перемещение — прошлый век! Альтернативы std::move в «C++ будущего»

Время на прочтение4 мин
Количество просмотров17K

Каждый раз, когда мы пишем класс, управляющий ресурсами, мы задумываемся о том, что, скорее всего, для него придётся писать move-конструктор и move-присваивание. Ведь иначе объекты такого типа становятся неуклюжими, как std::mutex, ими тяжело пользоваться на практике: ни вернуть из функции, ни передать в функцию по значению, ни положить в вектор — а если положить его в другой класс как один из членов, то тот класс также «заболевает».


Положим, мы преодолели свою лень (хотя в Rust таких проблем нет!) и садимся писать move-операции для нашего класса. Проблема в том, что move-семантика в C++ имеет фундаментальное ограничение: каждый владеющий ресурсами тип с move-операциями должен иметь пустое состояние, то есть состояние с украденными ресурсами. Его нужно описывать в документации и предоставлять ему поддержку, то есть тратить время и силы на то, что нам не нужно.


Для абстрактных типов данных пустое состояние обычно бессмысленно — если у объекта украли его ресурсы, то он не сможет выполнять свои обычные функции. Но мы вынуждены это делать, чтобы реализовать move-семантику. Для некоторых типов пустое состояние недопустимо: open_file (в противовес теоретическому file), not_null_unique_ptr<T> (в противовес unique_ptr<T>).


Говоря словами Arthur O'Dwyer, мы заказывали телепорт, а нам дали «вас клонируют и убивают первоначальную копию». Чтобы вернуть себе телепорт, проходите под кат!

Читать дальше →
Всего голосов 24: ↑22 и ↓2+20
Комментарии174

Сверхсовременные иммутабельные структуры данных

Время на прочтение22 мин
Количество просмотров30K
Годами эксперты в С++ рассуждают о семантике значений, иммутабельности и разделении ресурсов за счет коммуникации. О новом мире без мьютексов и гонок, без паттернов Command и Observer. На деле все не так просто. Главная проблема по-прежнему в наших структурах данных.



Иммутабельные структуры данных не меняют своих значений. Чтобы что-то с ними сделать, нужно создавать новые значения. Старые же значения остаются на прежнем месте, поэтому их можно без проблем и блокировок читать из разных потоков. В итоге ресурсы можно совместно использовать более рационально и упорядоченно, ведь старые и новые значения могут использовать общие данные. Благодаря этому их куда быстрей сравнить между собой и компактно хранить историю операций с возможностью отмены. Все это отлично ложится на многопоточные и интерактивные системы: такие структуры данных упрощают архитектуру десктопных приложений и позволяют сервисам лучше масштабироваться. Иммутабельные структуры — секрет успеха Clojure и Scala, и даже сообщество JavaScript теперь пользуется их преимуществами, ведь у них есть библиотека Immutable.js, написанная в недрах компании Facebook.

Под катом — видео и перевод доклада Juan Puente с конференции C++ Russia 2019 Moscow. Хуан рассказывает про Immer — библиотеку иммутабельных структур для C++. В посте:

  • архитектурные преимущества иммутабельности;
  • создание эффективного персистентного векторного типа на основе RRB-деревьев;
  • разбор архитектуры на примере простого текстового редактора.

Всего голосов 84: ↑84 и ↓0+84
Комментарии57

Создание Minecraft за одну неделю на C++ и Vulkan

Время на прочтение8 мин
Количество просмотров30K
Я поставил перед собой задачу воссоздания с нуля Minecraft за одну неделю с помощью собственного движка на C++ и Vulkan. Меня вдохновил на это Hopson, который сделал то же самое при помощи C++ и OpenGL. В свою очередь, его вдохновил Шейн Бек, которого вдохновила Minecraft, источником вдохновения для которой была Infiniminer, при создании которой, предположительно, вдохновлялись реальными горными промыслами.


Репозиторий GitHub этого проекта находится здесь. У каждого дня есть своя git-метка.

Разумеется, я не планировал в буквальном смысле воссоздавать Minecraft. Этот проект должен был стать обучающим. Я хотел изучить использование Vulkan в чём-то более сложном, чем vulkan-tutorial.com или демо Саши Виллема. Поэтому основной упор сделан на проектирование Vulkan-движка, а не на дизайн игры.

Задачи


Разработка на Vulkan намного медленнее, чем на OpenGL, поэтому я не смог включить в игру многие функции настоящей Minecraft. Нет ни мобов, ни крафта, ни красного камня, ни физики блоков, и т.п. С самого начала цели проекта были следующими:

  • Создание системы рендеринга рельефа
    • Мешинг
    • Освещение
  • Создание системы генератора рельефа
    • Рельеф
    • Деревья
    • Биомы
  • Добавление возможности изменения рельефа и перемещения блоков

Мне нужно было найти способ реализовать всё это без добавления в игру GUI, потому что я не смог найти никаких библиотек GUI, работающих с Vulkan и простых в интеграции.
Всего голосов 21: ↑17 и ↓4+13
Комментарии11

О работе ПК на примере Windows 10 и клавиатуры ч.2

Время на прочтение16 мин
Количество просмотров43K
В этой части мы рассмотрим какой путь проходит информация о нажатой клавише от клавиатуры до CPU, будет очень много картинок и это не последняя часть. Я буду рассказывать об этом с точки зрения программиста который пишет в режиме пользователя — пользовательские програмы, web, мобильные приложения — поэтому здесь могут быть неточности. Люди занимающиеся электроникой навряд ли найдут для себя что-то полезное. Первая часть находится здесь.


Проблема высшего программистского образования в том что студенты весьма подробно изучают отдельные аспекты вырванные из контекста не понимая как это всё увязывается вместе. Несколько семестров высшей математики, чтобы понимать физику, чтобы понимать электротехнику, электроприборы, ассемблер, ОС, алгоритмы, системное программирование и куча других предметов утрамбованных в стандартную пятилетнюю программу. Обилие деталей и никто не объясняет как это вписывается в общую картину, предполагается что через 5 лет студент сам увяжет это в голове, а потом пойдёт работать с .Net и никогда не притронется к электронике и режиму ядра. Я считаю, что не нужно так подробно знать о работе компьютера, достаточно общего понимания что происходит ниже по технологическому стеку. Если бы люди составляющие программы обучения для ВУЗов открывали автошколы, вы бы учили русский язык, каллиграфию и гидродинамику, потому как надо общаться с инспекторами, менять жидкости и писать объяснительные. В статье будут некоторые неточности, так что для сдачи экзамена по профильным предметам она не подойдёт, но после неё будет легче понять устройство ПК.

Под катом трафик.
Читать дальше →
Всего голосов 41: ↑29 и ↓12+17
Комментарии68

Перегрузка в C++. Часть III. Перегрузка операторов new/delete

Время на прочтение11 мин
Количество просмотров22K

Продолжаем серию «C++, копаем вглубь». Цель этой серии — рассказать максимально подробно о разных особенностях языка, возможно довольно специальных. Эта статья посвящена перегрузке операторов new/delete. Это третья статья из серии, первая, посвященная перегрузке функций и шаблонов, находится здесь, вторая, посвященная перегрузке операторов, находится здесь. Статья завершает цикл из трех статей, посвященный перегрузке в C++.

Читать дальше →
Всего голосов 12: ↑12 и ↓0+12
Комментарии14

МЭМС акселерометры, магнитометры и углы ориентации

Время на прочтение8 мин
Количество просмотров33K


При разработке устройств, в которых необходимо оценивать углы ориентации, может встать вопрос — какой МЭМС датчик выбрать. Производители датчиков приводят множество параметров, из которых нам требуется получить полезную информацию о качестве датчика.

Чтобы понять, на какие точности углов мы можем рассчитывать, нужно приложить некоторое количество усилий.

TL;DR: Описан небольшой скрипт для Octave/MATLAB, позволяющий оценить ошибки расчёта углов ориентации по измерениям МЭМС акселерометров и магнитометров. На входе скрипта — параметры датчиков из даташитов (и/или погрешности калибровки). Статья может быть полезна тем, кто начинает использовать инерциальные датчики в своих устройствах. Небольшой ликбез по датчикам прилагается. Ссылка на гитхаб тоже.
Вот как мы решили эту задачу:
Всего голосов 26: ↑26 и ↓0+26
Комментарии23

Супер-выразительный код с привлечением уровней абстракций

Время на прочтение5 мин
Количество просмотров8.3K

Предлагаю вашему вниманию перевод статьи Super expressive code by Raising Levels of Abstraction


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


Проблема


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

Читать дальше →
Всего голосов 12: ↑9 и ↓3+6
Комментарии27

Ключевое слово «mutable» в C++

Время на прочтение4 мин
Количество просмотров93K
Ключевое слово mutable относится к малоизвестным уголкам языка С++. В то же время оно может быть очень полезным, или даже необходимым в случае, если вы хотите строго придерживаться const-корректности вашего кода или писать лямбда-функции, способные изменять своё состояние.

Пару дней назад Eric Smolikowski написал в своём твиттере:

«Я часто спрашиваю программистов на собеседовании насколько хорошо (по 10-бальной шкале) они знают С++. Обычно они отвечают 8 или 9. И тогда я спрашиваю что такое „mutable“. Они не знают. :)»

Впечатления от таких вопросов и ответов у меня двоякие. С одной стороны, задавать подобные вопросы на собеседовании — дело бесполезное, это почти ничего не говорит о способностях интервьюируемого. Но, с другой стороны, ключевое слово mutable незаслуженно забыто многими программистами, а ведь оно может быть очень полезным в некоторых сценариях.
Читать дальше →
Всего голосов 39: ↑37 и ↓2+35
Комментарии27

Восемь возможностей C++17, которые должен применять каждый разработчик

Время на прочтение9 мин
Количество просмотров128K

Мы поговорим о восьми удобных изменениях, которые влияют на ваш повседневный код. Четыре изменения касаются самого языка, а ещё четыре — его стандартной библиотеки.


Вам также может быть интересна статья Десять возможностей C++11, которые должен использовать каждый C++ разработчик
Читать дальше →
Всего голосов 35: ↑33 и ↓2+31
Комментарии47

Рефлексия в C++14

Время на прочтение15 мин
Количество просмотров31K
Данная статья является расшифровкой (с небольшими правками) доклада Антона antoshkka Полухина — “Немного магии для C++14”.

Я тут недавно ковырялся с C++ и случайно открыл пару новых приемов метапрограммирования, которые позволяют делать рефлексию в C++14. Пара мотивационных примеров. Вот у вас есть какая-то POD структура, в ней какие-то поля:

struct complicated_struct {
    int i;
    short s;
    double d;
    unsigned u;
};

Количество полей и их имена не имеют значение, важно то, что с этой структуры мы можем написать следующий кусочек кода:

#include <iostream>
#include "magic_get.hpp"

struct complicated_struct { /* … */ };

int main() {
    using namespace pod_ops;
    complicated_struct s {1, 2, 3.0, 4};
    std::cout << "s == " << s << std::endl; // Compile time error?
}

Функция main, в ней создаем переменную нашей структуры, как-то ее инициализируем через aggregate инициализацию, а потом эту переменную пытаемся вывести в std::cout. И в этот момент у нас, по идее, должна быть ошибка компиляции: мы не определили оператор вывода в поток для нашей структуры, компилятор не знает как все это скомпилировать и вывести. Однако, оно скомпилируется и выведет содержимое структуры:

antoshkka@home:~$ ./test
s == {1, 2, 3.0, 4}

Читать дальше →
Всего голосов 40: ↑38 и ↓2+36
Комментарии33

Информация

В рейтинге
Не участвует
Откуда
Киев, Киевская обл., Украина
Зарегистрирован
Активность