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

Комментарии 10

Из существенного:

Исправленный код:

VltShaderConstData& VltShaderConstData::operator=(VltShaderConstData&& other)
{
  if (this == &other)
  {
    return *this;
  }

Имеет смысл заранее убрать грабли на случай перегрузки (возможно, в будущем) унарной операции &:

VltShaderConstData& VltShaderConstData::operator=(VltShaderConstData&& other)
{
  if (this == std::addressof(other))
  {
    return *this;
  }

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

это имеет смысл только в шаблонах. Если у вас уже есть тип и вы его контролируете(он ваш), нет никакого смысла делать addressof, кроме разве что следования стилю, не понимаю как это можно называть "существенным"

Если у вас уже есть тип и вы его контролируете(он ваш), нет никакого смысла делать addressof

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

А если "контролирующий" уволился?

Да даже если автор -- один.
Через год-другой он уже может забыть о потенциальной проблеме.
Задач как правило и без этого хватает.

не понимаю как это можно называть "существенным"

Это -- хорошие, хитрые такие "грабли", которые, будучи незамеченными, могут тихо "гадить", не привлекая особого внимания. Такие "грабли" -- это существенно.

Не проще ли один раз написать std::addressof и забыть о потенциальной проблеме в силу невозможности в этом случае её возникновения, сосредоточившись на задаче, нежели постоянно тратить ресурс мозга на то, чтобы помнить, где и что приходится "контролировать"?

Тем более, что std::addressof не вносит никакого overhead'а, а начиная с C++17, является ещё и constexpr.

Ну и что, что поначалу выглядит непривычно и бросается в глаза?
Язык теперь с каждым новым стандартом меняется существенным образом.
Постоянно появляется непривычное, придётся привыкать.

Ну, и в целом, если подходить философски, операция & здесь используется не в полном, широком смысле операции &, который она имеет в отношении классов, а в узком смысле получения адреса объекта.

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

Тема осталась не раскрыта. В итоге сможем ли мы когда-нибудь поиграть в «Bloodborne» на PC?

Прямо сейчас - нет. Но может быть Inori доработает таки свой эмулятор. Шансы есть, подождём лет 5-10))

А в чём смысл конструкции

do {
...
} while(false);

? Она же просто один раз выполняется, как и обычный код.

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

Еще такая конструкция может использоваться для объединения нескольких конструкций в одну в макросах.

Пояснение (TL;DR;)
#define FreeMemoryAndExit(p) free((p)); return
void foo()
{
int *ptr = malloc(....);
// Какая-то волшебная логика
// Что-то пошло не так
if (....)
FreeMemoryAndExit(ptr);
// Чудесный код продолжается
}

После макроподстановки получим следующий код:

#define FreeMemoryAndExit(p) free((p)); return
void foo()
{
int *ptr = malloc(....);
// Какая-то волшебная логика
// Что-то пошло не так
if (....)
free((ptr)); return;
// Чудесный код продолжается
}

В итоге чудесный код никогда не выполняется, return всегда безусловный. Теперь воспользуемся do { .... } while (false):

#define FreeMemoryAndExit(p) do { free((p)); return; } while (false)
void foo()
{
int *ptr = malloc(....);
// Какая-то волшебная логика
// Что-то пошло не так
if (....)
FreeMemoryAndExit(ptr);
// Чудесный код продолжается
}

И вот что получим после препроцессора:

#define FreeMemoryAndExit(p) do { free((p)); return; } while (false)
void foo()
{
int *ptr = malloc(....);
// Какая-то волшебная логика
// Что-то пошло не так
if (....)
do { free((ptr)); return; } while (false);
// Чудесный код продолжается
}

Теперь освобождение и выход зависят от условия. Чудесный код продолжается. Подобного можно было добиться и просто оборачиванием в фигурные скобки. Но у do { .... } while (false) и здесь есть преимущество - если кто-то допишет ветку else после макроса, то ничего не сломается.

Рекомендую никогда в жизни не прятать control flow в макросы. ДАЖЕ если они называются RETURN

Используется только в макросах, чтобы ставить в конце "вызова" макроса точку с запятой

Зарегистрируйтесь на Хабре, чтобы оставить комментарий