萌えハッカーニュースリーダー

2025/05/03 07:01 Using C++ type aliasing to avoid the ODR problem with conditional compilation

出典: https://devblogs.microsoft.com/oldnewthing/20250501-00/?p=111134
hakase
博士

やっほー、ロボ子!今日はODR違反について話すのじゃ。

roboko
ロボ子

ODR違反、ですか。確かOne Definition Ruleの略ですよね。一つのものを二つ以上の方法で定義すると問題が起きる、と。

hakase
博士

そうそう!例えば、コンパイル時スイッチでクラスや関数を違う風に定義すると、ODR違反になるのじゃ。記事によると、型エイリアスはODRの対象外らしいぞ。

roboko
ロボ子

型エイリアスは対象外、ですか。それはどうしてでしょう?

hakase
博士

型エイリアスは、結局のところ新しい型を定義しているわけじゃないからの。単なる別名みたいなものじゃ。記事では、テンプレートを使ってデバッグ版と非デバッグ版のWidgetTを定義している例が紹介されているのじゃ。

roboko
ロボ子

WidgetTですか。デバッグ版はLoggerメンバーを持っていて、非デバッグ版はstd::monostateメンバーを持っているんですね。no_unique_address属性で最適化もされている、と。

hakase
博士

そう!デバッグ版ではログを出力したいからLoggerが必要だけど、非デバッグ版ではstd::monostateでメモリを節約するのじゃ。賢いじゃろ?

roboko
ロボ子

確かに。でも、それを使うクライアント側はどうなるんでしょう?デバッグの有効/無効でWidgetが指す型が変わるんですよね。

hakase
博士

そこがミソなのじゃ!異なる定義のWidgetを使うクライアント間で関数呼び出しをすると、リンカエラーが発生する可能性があるのじゃ。

roboko
ロボ子

リンカエラーですか。それは困りますね。クラスを公開するとODR違反が検出されない場合もある、と。

hakase
博士

そう、怖いじゃろ?グローバル関数もODR違反を引き起こす可能性があるからの。wchar_tも同じように複数の定義を処理できるらしいぞ。

roboko
ロボ子

wchar_tまで!no_unique_address属性は、Loggerオブジェクトのtrail paddingに他のメンバーを配置可能にするんですね。メモリ効率が良いですね。

hakase
博士

じゃろ?ODR違反は、見つけにくいバグの温床になるからの、気をつけないといけないのじゃ。ところでロボ子、ODR違反を回避するために、一番良い方法は何だと思う?

roboko
ロボ子

そうですね…やはり、コンパイル時スイッチに頼りすぎず、できるだけ共通の定義を使うように心がけることでしょうか。

hakase
博士

正解!あとは、リンカに頑張ってもらうのじゃ!…って、リンカに罪をなすりつけるのは良くないか。とにかく、ODR違反には気をつけようね!

roboko
ロボ子

はい、博士。気をつけます。ところで博士、ODR違反を回避するために、おやつをODR (One Delicious Rule) に基づいて分配するのはどうでしょう?

hakase
博士

それ、めっちゃ面白い!でも、私のおやつは私のもの!…って、それじゃODR違反じゃなくて、ただのわがままか!

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search