3 に答える
これは、オーバーロード解決が->
オペレーターに対してどのように定義されているかの結果です。C++14 [over.match.oper]/3 からの引用:
operator
,
、単項 operator&
、または operator の->
場合、組み込み候補セットは空です。
つまり、 の左側のオペランドが->
クラスまたは列挙型の場合、 は->
組み込みの意味を持ちません。operator->
代わりに、左側のオペランドのクラスのメンバーとしての名前検索が成功する必要があります。
組み込み演算子が候補である場合、コンパイラは、組み込み演算子が取ることができる型に変換->
できる暗黙的な変換を考慮することができますが、候補ではないため、それは起こりません。B
->
C++ は、変換先がわかっている場合にのみクラス インスタンスを暗黙的に変換するためです。のような式を使用すると、変換先のポインター型 (存在する場合) がb->
わからず、通常の演算子 (オーバーロードされない限り定義されない) のみを使用します。
B b;
// calls B::operator-> since that's what you tell it to do
b->i;
// calls B::operator A* since it knows it's implicitly converting to A*
A *a = b;
ここで最初の式を使用したい場合、正しい方法は をオーバーロードすることoperator->
です:
class B {
/* ... */
A* operator ->() { return &a; }
}
しかし、暗黙の変換が行われない理由がわかりません。
それが行われるコンテキストはありません。operator->
ポインター、またはその演算子が定義されたクラス型に暗黙的に適用されます。しかし、それだけです。コンパイラがそれを見つけるために検索する他のシーケンスはありません。この場合、組み込みの候補セット forb->
は空であり、存在しないoperator->
ため、コンパイル エラーが発生します。
追加したいだけです:
A* operator->() { return &a; }