Chromium Chronicle n.o 24: StrongAlias, IdType y TokenType

Episodio 24: de Vocabulario Anforowicz en Bellevue, Washington (agosto de 2021)
Episodios anteriores

¿Puedes encontrar el error en el siguiente código? ¿Conoces el error en una revisión de código, cuando solo mira el sitio de llamada?

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

En ocasiones, es posible que el mismo tipo represente valores de dominios incompatibles. Esto suele suceder con los tipos de datos no específicos, como números enteros o cadenas. En el ejemplo anterior, se ilustra cómo esto puede causar errores. Afortunadamente, //base de Chromium facilita la introducción de tipos explícitos y 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);

Los tipos separados mejoran la legibilidad. Además, StrongAlias detecta combinaciones de tipos en el tiempo de compilación:

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

El compilador ve que los tipos son incompatibles porque tienen una "etiqueta" diferente el tipo de letra. StrongAlias acepta cualquier tipo como "etiqueta" el tipo de letra. El ejemplo muestra que la “etiqueta” tipo no necesita una definición de tipo en ninguna parte: la declaración in situ de una clase inexistente funciona bien.

En el futuro, en lugar de un tipo no específico (por ejemplo, un bool, un int o una cadena), considera estas alternativas:

  • Usa base::IdType32<TagType> en lugar de int32_t como identificador.
  • Usa base::TokenType<TagType> en lugar de un base::UnguessableToken no específico.
  • Cómo usar una clase enum en lugar de un bool (por ejemplo, kForReload, kNotForReload en lugar de true, false).
  • Reemplaza otros tipos no específicos por base::StrongAlias<TagType, SomeWrappedType>.