Chromium Chronicle #24: StrongAlias، IdType و TokenType

قسمت 24: توسط Łukasz Anforowicz در Bellevue, WA (اگوست 2021)
قسمت های قبلی

آیا می توانید اشکال در کد زیر را تشخیص دهید؟ آیا وقتی فقط به callsite نگاه می کنید، اشکال را در بررسی کد مشاهده می کنید؟

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

همین نوع ممکن است گاهی اوقات مقادیری از دامنه های ناسازگار را نشان دهد. این معمولا برای انواع داده های غیر اختصاصی مانند اعداد صحیح یا رشته ها اتفاق می افتد. مثال بالا نشان می دهد که چگونه این می تواند باعث ایجاد باگ شود. خوشبختانه، //base Chromium معرفی انواع واضح و متمایز را آسان می کند:

#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 ​​هر نوع را به عنوان نوع "برچسب" می پذیرد. مثال نشان می‌دهد که نوع "برچسب" حتی به تعریف نوع در هیچ کجا نیاز ندارد - یک اعلان پیشروی کلاس غیر موجود به خوبی کار می‌کند.

در آینده، به جای یک نوع غیر اختصاصی (مثلاً bool، int، رشته)، این گزینه ها را در نظر بگیرید:

  • به جای استفاده از int32_t به عنوان شناسه از base::IdType32<TagType> استفاده کنید.
  • از base::TokenType<TagType> به جای base::UnguessableToken استفاده کنید.
  • از یک کلاس enum به جای bool استفاده کنید (مثلا kForReload ، kNotForReload به جای true ، false ).
  • base::StrongAlias<TagType, SomeWrappedType> سایر انواع غیر اختصاصی را جایگزین کنید.