Chromium Chronicle #24: StrongAlias, IdType và TokenType

Tập 24: của Łukasz Anforowicz ở Bellevue, Washington (tháng 8 năm 2021)
Các tập trước

Bạn có thể phát hiện lỗi trong mã bên dưới không? Bạn có thấy lỗi trong quá trình xem xét mã, khi chỉ xem trang web gọi không?

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

Cùng một loại đôi khi có thể biểu thị các giá trị từ các miền không tương thích. Điều này thường xảy ra với các loại dữ liệu không cụ thể như số nguyên hoặc chuỗi. Ví dụ trên minh hoạ cách điều này gây ra lỗi. May mắn là //base của Chromium giúp bạn dễ dàng giới thiệu các loại rõ ràng, riêng biệt:

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

Các kiểu riêng biệt giúp cải thiện khả năng đọc. Ngoài ra, StrongAlias phát hiện các kiểu kết hợp loại tại thời điểm biên dịch:

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

Trình biên dịch thấy rằng các kiểu này không tương thích vì chúng có một loại "thẻ" khác. StrongAlias chấp nhận mọi loại làm loại "thẻ". Ví dụ cho thấy rằng loại "thẻ" thậm chí không cần định nghĩa loại ở bất cứ đâu. Việc khai báo tại chỗ của một lớp không tồn tại sẽ hiệu quả.

Trong tương lai, thay vì một loại không cụ thể (ví dụ: bool, số nguyên, chuỗi), hãy cân nhắc sử dụng những phương án thay thế sau:

  • Sử dụng base::IdType32<TagType> thay vì dùng int32_t làm giá trị nhận dạng.
  • Sử dụng base::TokenType<TagType> thay vì một base::UnguessableToken không cụ thể.
  • Sử dụng một lớp enum thay vì bool (ví dụ: kForReload, kNotForReload thay vì true, false).
  • Thay thế các loại không cụ thể khác bằng base::StrongAlias<TagType, SomeWrappedType>.