The Chromium Chronicle #24: StrongAlias وIdType وTokenType

الحلقة 24: من تأليف "لوكاس أنفوروفيتش" في مدينة "بلفيو"، واشنطن (آب/أغسطس 2021)
الحلقات السابقة

هل يمكنك اكتشاف الخطأ في الرمز أدناه؟ هل ترى الـ خطأ في مراجعة التعليمات البرمجية، عند النظر إلى موقع الاتصال فقط؟

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 أي نوع باعتباره "العلامة" الكتابة. يوضح المثال أن "العلامة" النوع لا يحتاج إلى تعريف نوع في أي مكان — من الأفضل الإعلان عن فئة غير موجودة مسبقًا في مكانه.

في المستقبل، بدلاً من استخدام نوع غير محدد (على سبيل المثال، قيمة منطقية أو عدد صحيح أو سلسلة)، ضع في اعتبارك هذه البدائل التالية:

  • يمكنك استخدام base::IdType32<TagType> بدلاً من استخدام int32_t كمعرّف.
  • استخدِم base::TokenType<TagType> بدلاً من سمة base::UnguessableToken غير محدّدة.
  • استخدام فئة enum بدلاً من قيمة منطقية (على سبيل المثال، kForReload وkNotForReload بدلاً من true وfalse).
  • استبدِل الأنواع الأخرى غير المحدّدة بـ base::StrongAlias<TagType, SomeWrappedType>.