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 deint32_t
como um identificador. - Use
base::TokenType<TagType>
em vez de umbase::UnguessableToken
não específico. - Usar uma classe de enumeração em vez de um booleano
Por exemplo,
kForReload
,kNotForReload
em vez detrue
,false
. - Substitua outros tipos não específicos por
base::StrongAlias<TagType, SomeWrappedType>
.