C ++クラスメンバー名検索の問題(標準N3225の文言に関する)
-
13-10-2019 - |
質問
私は標準の10.2/13について非常に混乱しています
注:名前のルックアップの結果が明確であっても、複数のサブオブジェクトで見つかった名前の使用はまだ曖昧かもしれません(4.11、5.2.5、5.3.1、11.2)。
struct B1 {
void f();
static void f(int);
int i;
};
struct B2 {
void f(double);
};
struct I1: B1 { };
struct I2: B1 { };
struct D: I1, I2, B2 {
using B1::f;
using B2::f;
void g() {
f(); // Ambiguous conversion of this
f(0); // Unambiguous (static)
f(0.0); // Unambiguous (only one B2)
int B1::* mpB1 = &D::i; // Unambiguous
int D::* mpD = &D::i; // Ambiguous conversion
}
};
なぜこれが明確なint b1 ::* mpb1 =&d :: i; //明確です
Visual C ++、GCC、Clangはすべて、D :: I!へのあいまいなアクセスであると言います!
文言はコアの問題#39に関連しているようですhttp://www.openstd.org/jtc1/sc22/wg21/docs/cwg_defects.html#39, 、そして最終的な提案はここにあります: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf
新しいアルゴリズムベースの文言(10.2/3-10.2/6)はさらに混乱していることがわかりました。 3-10.2/6。例外として10.2/9-10.2/11を取ることができますが、10.2/13については特に混乱しています。 10.2/13の意図についてはわかりません。
10.2/3-10.2/6に従って、10.2/13の例をどのように検索する必要がありますか? 10.2/13の意図、つまり、10.2/13が10.2/3-10.2/6の例外と見なされる状況はどうですか?
いくつかのヒントをください。どうもありがとうございます。
いくつかの考えの後、私は10.2/13の意図が私にとって明確だと思います。
int b1 ::* mpb1 =&d :: i; //明確です
これは明確でなければならず、現在のコンパイラはこれについて間違っています。クラスメンバーへのポインターの初期化はまだオブジェクトへのアクセスに関与していないため、これは明確です。
int d ::* mpd =&d :: i; //あいまいな変換
これは、実際には、int b1 ::*mpb1からint d ::*mpdに変換すると、曖昧な基本クラスのために変換が曖昧になることを意味します。
解決
これ:
int B1::* mpB1 = &D::i; // Unambiguous
結果がに割り当てられているため、明確です pointer to member
クラスBのB
だからそれはどちらが関係ありません i
オフセットがBメンバー(親Dクラスではなく)に関連するように選択されます。
ですから、それはあなたと私にとって明確ではありませんが、コンパイラーがそれを処理できるとは思いません。
他のヒント
B1 ::*ケースの場合、解釈は明確であり、単にB1の開始からiへのオフセットです。
5.3.1/3:
struct A { int i; };
struct B : A { };
... &B::i ... // has type int A::*
したがって、最初の場所では、&d :: I Type B1 ::*を作成することです。それで:
int B1::* mpB1 = &D::i; // Unambiguous
簡単です。その後、関心は次のとおりです。
int D::* mpD = &D::i; // Ambiguous conversion
ここでは、RHSはタイプB1 ::*であり、参照されているベースを決定する必要があるため、変換が必要です。
ISO IEC 14882 2003セクション10の簡単なチェックには、この例やこれに似たものがありません。 C ++ 0xは 下書き 標準、およびVC ++/GCC/Clangはそれに準拠していません。
私の推測:これは新しいものの副産物です auto
タイピングであり、古いC ++標準では見つかりません。
fwiw、私はこの質問のusenetコピーに与えた答えをコピーしています:
こんにちは、みんな、
私は標準のN3225 10.2/13について非常に混乱しています
注:名前のルックアップの結果が明確であっても、複数のサブオブジェクトで見つかった名前の使用はまだ曖昧かもしれません(4.11、5.2.5、5.3.1、11.2)。
struct B1 {
void f();
static void f(int);
int i;
};
struct B2 {
void f(double);
};
struct I1: B1 { };
struct I2: B1 { };
struct D: I1, I2, B2 {
using B1::f;
using B2::f;
void g() {
f(); // Ambiguous conversion of this
f(0); // Unambiguous (static)
f(0.0); // Unambiguous (only one B2)
int B1::* mpB1 = &D::i; // Unambiguous
int D::* mpD = &D::i; // Ambiguous conversion
}
};
なぜこれが明確なint b1 ::* mpb1 =&d :: i; //明確です
&D::i
タイプがあります int B1::*
, 、および明確にデータメンバーを指します i
のB1
. 。あなたがそれを抑制した場合 D
オブジェクトまたはそれをaに割り当てる場合 int
D::*
, 、必要に応じて曖昧さが得られます。
Visual C ++、GCC、Clangはすべて、D :: I!へのあいまいなアクセスであると言います!
これらのコンパイラはまだ10.2を実装していません。
文言はコアの問題#39に関連しているようです http://www.openstd.org/jtc1/sc22/wg21/docs/cwg_defects.html#39, 、そして最終的な提案はここにあります: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1626.pdf新しいアルゴリズムベースの文言(10.2/3-10.2/6)はさらに混乱していることがわかりました。 3-10.2/6。例外として10.2/9-10.2/11を取ることができますが、10.2/13については特に混乱しています。 10.2/13の意図についてはわかりません。
あなたが理解していないことを示す例を与える必要があります。
10.2/3-10.2/6に従って、10.2/13の例をどのように検索する必要がありますか? 10.2/13の意図、つまり、10.2/13が10.2/3-10.2/6の例外と見なされる状況はどうですか?
新しいアルゴリズムベースのルックアップルールは、コンパイル時間/ルックアップの懸念からランタイムの懸念(一意のオブジェクトを見つける)を分離します(名前が指す宣言を見つける)。
以下は、新しい言葉遣いとよく形成されています。
struct Z { int z; };
struct X : Z { };
struct Y : Z { };
struct A : X, Y { };
struct B : A {
using A::z;
};
宣言 using A::x;
宣言を指すメンバー名をBに紹介します Z::z
. 。宣言的な文脈では、これはまったく問題ありません。アクセスしたときにのみエラーが上昇します B::z
メンバーアクセス式として(5.2.5)。
メンバーのポインターケースについてこれを間違えたことを気にしないでください。 私もそうしました 過去に、そして対応する 発行報告書 実際にC ++ 0xドラフトにしました。彼らは幸運にも それを元に戻しました 彼らが変化が間違っていることに気付いたとき。