Chromium Chronicle #24:StrongAlias、IdType 和 TokenType

第 24 集:作者:華盛頓州貝爾維尤的沃卡斯安弗維奇 (Uukasz Anforowicz) (2021 年 8 月)
前一集

您能在下方程式碼中發現錯誤嗎?如果在查看呼叫點時,是否在程式碼審查中看到錯誤

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

相同類型有時可能代表不相容網域的值。這通常發生在非特定資料類型,例如整數或字串。以上範例說明這可能造成錯誤的原因。幸好,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);

分隔不同的類型可提高可讀性。此外,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);
      ^

編譯器發現類型不相容,因為類型有不同的「標記」類型。StrongAlias 接受任何類型做為「標記」類型。這個範例顯示,「tag」類型甚至不需要任何位置類型定義,而對於不存在類別的前後宣告皆可正常運作。

日後,請考慮以下替代選項,而非特定非特定類型 (例如 bool、int、字串):

  • 使用 base::IdType32<TagType> 做為 ID,不要使用 int32_t
  • 使用 base::TokenType<TagType>,而非非特定的 base::UnguessableToken
  • 使用列舉類別,而非布林值 (例如 kForReloadkNotForReload,而非 truefalse)。
  • 將其他非特定類型替換為 base::StrongAlias<TagType, SomeWrappedType>