26

次のコードを見てください

struct A { using type = int; };
struct B : private A {};
struct C : B { using base_type = A; };

gcc 6.1、clang 3.8 、および msvc 2015 update 3 のすべては、これをコンパイルすることを拒否Aします。gcc はのデフォルト コンストラクタを参照しているようです。msvc と clang はそうではないようです。CABAusing base_type = AA

おそらく、コンパイル エラーは、継承によってトリガーされた名前の挿入が原因である可能性があります (すべてのコンパイラが正常に動作するように変更using base_type = Aするため)。using base_type = ::A

より具体的には、

  1. 私が理解したように、 のようA::typeに、Aは単なるクラス名 (gcc はそれを関数名と誤解しますが) であり、C 内部 Aではなく、またはに導入されBます。この名前が のプライベートと見なされるのはなぜBですか?
  2. このコンパイル エラーはバグと見なすべきですか、それとも標準の仕様の特殊なケースですか?
4

2 に答える 2

28

非修飾名ルックアップの規則によると、次のようになります。

(私のものを強調)

修飾されていない名前、つまりスコープ解決演算子 :: の右側に表示されない名前の場合、名前ルックアップは以下で説明するようにスコープを調べ、少なくとも 1 つの任意の種類の宣言を見つけた時点でルックアップを停止します。それ以上のスコープは検査されません

したがって、名前Aは最初に基本クラスのスコープで検出され、グローバル名前空間の名前はここでは考慮されません。その後、アクセス権チェックを行い、コンパイルに失敗します。

::Aグローバルスコープで名前を指定し、問題を解決して、修飾名のルックアップにします。

于 2016-07-04T08:26:54.543 に答える
2

コメントを回答として投稿する (コメントよりも回答のように思われる):

Aこれは、内部の名前検索がどのように機能するかによるものだと推測してCいます。A最初に、使用する前に のスコープ内の名前で何かが宣言されているかどうかを確認しますC。見つからないのでB、 Base クラスなので のスコープでチェックしています。Bs スコープで A が見つからない場合は、global namespace. しかし、何らかの形でAbyのプライベート継承がB2 回目のルックアップ、つまり のスコープ内で停止していますB。名前を使用して機能するためfully qualified、実際の問題は同じ行にあるに違いないと思います。

于 2016-07-04T08:28:43.520 に答える