Chromium Chronicle #24: strongAlias, IdType e TokenType

Episódio 24:de Batchukasz Anforowicz em Bellevue, WA (agosto de 2021)
Episódios anteriores

Você consegue identificar o bug no código abaixo? Você veria o bug em uma revisão de código, ao olhar apenas para o local da ligação?

Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());

Às vezes, o mesmo tipo pode representar valores de domínios incompatíveis. Isso geralmente acontece com tipos de dados não específicos, como números inteiros ou strings. O exemplo acima ilustra como isso pode causar bugs. Felizmente, o //base do Chromium facilita a introdução de tipos explícitos e distintos:

#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);

Tipos separados melhoram a legibilidade. Além disso, StrongAlias detecta combinações de tipos no tempo de compilação:

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);
      ^

O compilador percebe que os tipos são incompatíveis. porque têm uma "tag" diferente não é válido. StrongAlias aceita qualquer tipo como "tag" não é válido. O exemplo mostra que a tag o tipo não precisa de uma definição de tipo em lugar nenhum, declaração no local de encaminhamento de uma classe inexistente funciona bem.

No futuro, em vez de um tipo não específico (por exemplo, booleano, int ou string), considere estas alternativas:

  • Use base::IdType32<TagType> em vez de int32_t como um identificador.
  • Use base::TokenType<TagType> em vez de um base::UnguessableToken não específico.
  • Usar uma classe de enumeração em vez de um booleano Por exemplo, kForReload, kNotForReload em vez de true, false.
  • Substitua outros tipos não específicos por base::StrongAlias<TagType, SomeWrappedType>.