The Chromium Chronicle #24: StrongAlias, IdType, and TokenType
| 标题 | The Chromium Chronicle #24: StrongAlias, IdType, and TokenType | 
|---|---|
| 作者 | Łukasz Anforowicz in Bellevue, WA | 
| 发表时间 | August, 2021 | 
| 地址 | https://developer.chrome.com/blog/chromium-chronicle-24/ | 
你能发现下面代码中的错误吗?当你在Chroumium上进行代码审查的时候,你还能发现这个错误吗?比如这里和这里。
Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
有时候相同的数据类型可能代表着完全不兼容的数据,特别是像integers或者strings等一些基础数据类型。上面的例子生动的说明了这种错误是怎么发生的。还好的是,Chromium的//base引入了一种方法可以创建明确清晰的不同类型:
#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);
Separate types improve readability. Additionally, StrongAlias catches type mix-ups at compile time:
独立的类型明显地提高了可读性。另外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);
      ^
由于他们有不同的tag类型,所以编译器会将这两种类型当做是不同的不兼容的类型。StrongAlias可以将任意的类型当作为tag类型,甚至是使用不存在实际定义的原位前向声明类都可以。上面的例子中的class CommandDataTag和class CommandBufferIdTag实际上并没有定义。
在以后的编程中,考虑使用下面的替代类型而不是原始的基础数据类型(比如bool,int,string等):
- 使用base::IdType32<TagType>而不是int32_t
- 使用base::TokenType<TagType>而不是base::UnguessableToken
- 使用enum class而不是bool(比如,kForReload,kNotForReload而不是true和false)
- 使用base::StrongAlias<TagType, SomeWrappedType>替换其他的基础数据类型