Chromium Chronicle #24: StrongAlias, IdType và TokenType

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

Bạn có phát hiện thấy lỗi trong đoạn mã dưới đây không? Bạn có muốn thấy lỗi trong quá trình đánh giá mã, khi chỉ xem trang web gọi điện?

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

Đôi khi, cùng loại này 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 đối với các kiểu dữ liệu không cụ thể như số nguyên hoặc chuỗi. Ví dụ ở trên minh hoạ lý do việc này có thể gây ra lỗi. Thật may là //base của Chromium giúp bạn dễ dàng giới thiệu các loại nội dung phản cảm và khác 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 loại riêng biệt sẽ giúp cải thiện khả năng đọc. Ngoài ra, StrongAlias cũng bắt kịp các kết hợp kiểu dữ liệu 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 không tương thích, bởi vì chúng có một "thẻ" khác loại. StrongAlias chấp nhận mọi loại làm "thẻ" loại. Ví dụ cho thấy rằng "thẻ" kiểu dữ liệu thậm chí không cần định nghĩa kiểu ở bất cứ đâu—một việc khai báo chuyển tiếp tại chỗ cho lớp không tồn tại sẽ hoạt động tốt.

Trong tương lai, thay vì một loại không cụ thể (ví dụ: bool, int, chuỗi), hãy cân nhắc các lựa chọn thay thế sau:

  • Hãy sử dụng base::IdType32<TagType> thay vì int32_t làm giá trị nhận dạng.
  • Sử dụng base::TokenType<TagType> thay vì base::UnguessableToken không cụ thể.
  • Sử dụng một lớp enum thay vì boolean (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>.