Хроника Chromium № 24: StrongAlias, IdType и TokenType

Эпизод 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> .