エピソード 24: ワシントン州ベルビューでの LoadBalancersz Anforowicz(2021 年 8 月)
前のエピソード
以下のコードでバグを見つけます。Cloud Shell の バグ コードのレビューで コールサイトだけを見るとどうでしょうか。
Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
同じ型が、互換性のないドメインからの値を表すことがあります。
これは通常、整数や文字列など、具体的でないデータ型で発生します。
上記の例は、これによりバグがどのように発生するかを示しています。
幸い、Chromium の //base
を使用すると、明示的な異なる型を簡単に導入できます。
#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、string など)ではなく、 次の代替手段を検討してください。
- 識別子として
int32_t
を使用する代わりに、base::IdType32<TagType>
を使用します。 - 不特定の
base::UnguessableToken
ではなく、base::TokenType<TagType>
を使用します。 - ブール値の代わりに列挙型クラスを使用する
(例:
true
、false
ではなくkForReload
、kNotForReload
)。 - 他の非特定型を
base::StrongAlias<TagType, SomeWrappedType>
に置き換えます。