Chromium Chronicle #24: StrongAlias, IdType, dan TokenType

Episode 24: oleh Łukasz Anforowicz di Bellevue, WA (Agustus, 2021)
Episode sebelumnya

Dapatkah Anda menemukan bug pada kode di bawah ini? Apakah Anda melihat bug dalam peninjauan kode saat hanya melihat situs panggilan?

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

Jenis yang sama terkadang dapat mewakili nilai dari domain yang tidak kompatibel. Hal ini biasanya terjadi untuk jenis data non-spesifik seperti bilangan bulat atau string. Contoh di atas mengilustrasikan bagaimana hal ini dapat menyebabkan bug. Untungnya, //base Chromium memudahkan Anda memperkenalkan jenis yang eksplisit dan berbeda:

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

Jenis terpisah akan meningkatkan keterbacaan. Selain itu, StrongAlias menangkap campuran jenis pada waktu kompilasi:

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

Compiler melihat bahwa jenis tersebut tidak kompatibel, karena memiliki jenis "tag" yang berbeda. StrongAlias menerima jenis apa pun sebagai jenis "tag". Contoh ini menunjukkan bahwa jenis "tag" bahkan tidak memerlukan definisi jenis di mana pun—deklarasi maju yang diterapkan untuk class yang tidak ada berfungsi dengan baik.

Di masa mendatang, sebagai ganti jenis yang tidak spesifik (misalnya, bool, int, string), pertimbangkan alternatif berikut:

  • Gunakan base::IdType32<TagType>, bukan menggunakan int32_t sebagai ID.
  • Gunakan base::TokenType<TagType> bukan base::UnguessableToken non-spesifik.
  • Gunakan class enum, bukan bool (misalnya, kForReload, kNotForReload, bukan true, false).
  • Ganti jenis non-spesifik lainnya dengan base::StrongAlias<TagType, SomeWrappedType>.