Chromium Chronicle #24: StrongAlias, IdType ve TokenType

24. bölüm: Łukasz Anforowicz, Bellevue, Washington'da (Ağustos 2021)
Önceki bölümler

Aşağıdaki kodda hatayı tespit edebiliyor musunuz? Bir kod incelemesinde hatayı yalnızca çağrı sitesine bakarken görür müydünüz?

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

Aynı tür, bazen uyumsuz alanlardan gelen değerleri temsil edebilir. Bu durum genellikle tamsayılar veya dizeler gibi belirli olmayan veri türleri için geçerlidir. Yukarıdaki örnekte, bu durumun nasıl hatalara neden olabileceği gösterilmektedir. Neyse ki Chromium'un //base özelliği, uygunsuz ve farklı türleri tanıtmayı kolaylaştırıyor:

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

Ayrı türler okunabilirliği artırır. Ayrıca StrongAlias, derleme sırasında tür karmalarını yakalar:

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

Derleyici, farklı bir "etiket" türüne sahip oldukları için türlerin uyumsuz olduğunu görür. StrongAlias, "etiket" türü olarak her türü kabul eder. Örnek, "tag" türünün hiçbir yerde tür tanımına bile gerek olmadığını göstermektedir. Mevcut olmayan bir sınıfın yerinde ileriye dönük bildirimi sorunsuz bir şekilde çalışmaktadır.

Gelecekte, spesifik olmayan bir tür (ör. bir Bool, bir int, bir dize) yerine, aşağıdaki alternatifleri değerlendirin:

  • Tanımlayıcı olarak int32_t kullanmak yerine base::IdType32<TagType> kullanın.
  • Spesifik olmayan bir base::UnguessableToken yerine base::TokenType<TagType> kullanın.
  • Bool yerine bir enum sınıfı kullanın (örneğin, true, false yerine kForReload, kNotForReload).
  • Spesifik olmayan diğer türleri base::StrongAlias<TagType, SomeWrappedType> ile değiştir.