Chromium Chronicle #24: StrongAlias, IdType, dan TokenType

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

Dapatkah Anda melihat bug pada kode di bawah? Apakah Anda akan melihat yang bug dalam tinjauan kode, ketika melihat hanya {i>callsite<i}?

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

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

Di masa mendatang, alih-alih jenis non-spesifik (misalnya, bool, int, string), pertimbangkan alternatif berikut:

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