Эпизод 24: Лукаш Анфорович, Белвью, Вашингтон (август 2021 г.)
Предыдущие серии
Можете ли вы обнаружить ошибку в коде ниже? Увидите ли вы ошибку при проверке кода, просматривая только сайт вызова?
Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
Один и тот же тип иногда может представлять значения из несовместимых доменов. Обычно это происходит с неспецифическими типами данных, такими как целые числа или строки. Пример выше иллюстрирует, как это может вызвать ошибки. К счастью, //base
Chromium позволяет легко вводить явные отдельные типы:
#include "base/types/strong_alias.h"
// The first template argument of StrongAlias is a "tag" type.
// The "tag" type is used to distinguish between different
// StrongAlias types.
using CommandData = base::StrongAlias<class CommandDataTag, int>;
using CommandBufferId = base::StrongAlias<class CommandBufferIdTag, int>;
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
Отдельные типы улучшают читабельность. Кроме того, StrongAlias
улавливает путаницу типов во время компиляции:
test.cc:456:16: error: no matching function for call to 'CreateToken'
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
^~~~~~~~~~~
test.cc:123:7: note: candidate function not viable: no known conversion from
'StrongAlias<class CommandBufferIdTag, [...]>' to
'StrongAlias<class CommandDataTag, [...]>' for 1st argument
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
^
Компилятор видит, что типы несовместимы, поскольку у них другой тип «тега». StrongAlias
принимает любой тип в качестве типа «тег». Пример показывает, что тип «тег» даже нигде не нуждается в определении типа — предварительное объявление несуществующего класса на месте работает нормально.
В будущем вместо неспецифического типа (например, bool, int, string) рассмотрите следующие альтернативы:
- Используйте
base::IdType32<TagType>
вместо использованияint32_t
в качестве идентификатора. - Используйте
base::TokenType<TagType>
вместо неспецифическогоbase::UnguessableToken
. - Используйте класс перечисления вместо bool (например,
kForReload
,kNotForReload
вместоtrue
,false
). - Замените другие неспецифические типы на
base::StrongAlias<TagType, SomeWrappedType>
.