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 deint32_t
como identificador. - Usa
base::TokenType<TagType>
en lugar de unbase::UnguessableToken
no específico. - Cómo usar una clase enum en lugar de un bool
(por ejemplo,
kForReload
,kNotForReload
en lugar detrue
,false
). - Reemplaza otros tipos no específicos por
base::StrongAlias<TagType, SomeWrappedType>
.