コピーコンストラクターでのC ++名前空間の競合


33

私は次のコードを持っています:

namespace A {
    struct Foo {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};

A :: Fooにはbという名前のメンバーがないため、C ++コンパイラーは「c = foo.b」で不平を言います。:: FooでBarパラメータのタイプを変更すると、機能します。

私の質問は、この動作の背後にある合理的なものは何ですか(私はそれが継承によってBarがA名前空間に入るようにするという事実に関係していると思いますが、この理論をサポートするドキュメントを見つけることができません。


8
私は考えてそれが関連する引数依存の検索です。私はあなたが言語標準を参照する回答を求めていると思うので、「language-lawyer」にタグを付けました。そして非常に良い最初の質問です!すべての価値があります。
バトシェバ

名前空間Aには入りません。名前空間は、でBar別の構造体から継承させた場合に確認できますA。その場合、あいまいさはありません。継承はからすべてを追加し、よりみたいですA::FooBarの解決などFooA::Foo。申し訳ありませんが、これ以上正確に表現することはできません。
n314159

@Bathsheba関数名(または関数テンプレート名)またはテンプレート内の依存名を見つけるための引数型依存名ルックアップを意味するのですか
curiousguy

回答:


22

すべてのクラスには、その名前がメンバーとして挿入されています。したがって、名前を付けることができますA::Foo::Foo。これは注入されたクラス名と呼ばれます。

[クラス]

2クラス名は、クラス名が見られた直後に宣言されているスコープに挿入されます。クラス名もクラス自体のスコープに挿入されます。これは、注入されたクラス名と呼ばれます。アクセスチェックの目的で、注入されたクラス名はパブリックメンバー名であるかのように扱われます。

[basic.lookup]

3クラスの注入されたクラス名も、名前の非表示と検索のために、そのクラスのメンバーと見なされます。

引数型の非修飾名の検索は、クラスのスコープで始まるためBar、その基本クラスのスコープに進み、そこでメンバーを考慮します。そしてA::Foo::Foo、型名として検索します。

グローバルタイプ名を使用する場合は、周囲の(グローバル)名前空間で修飾します。

Bar(::Foo foo) {
    c = foo.b;
}

これは、注入されたクラス名が表示されないスコープで完全修飾ルックアップを実行しています。

フォローアップの「なぜ」の質問については、


5
@TedLyngmo-ADLは関数呼び出しで発生しますが、これらの特定の箇所には関係ありません。
StoryTeller-Unslander Monica

大木、読んでいて確信が持てなかった。ありがとう!
Ted Lyngmo

3
これは非常に面白いとリード線struct Bar:: A::Foo::Foo::Foo::Foo::Foo {}; が、文脈があるA::Foo::Fooコンストラクタを指定し、したがって、そこには多くのとして追加し続けることができないFooあなたが望むように。これは、関数をf次のように呼び出すことができるという事実に似ています(ただし、メカニズムは完全に異なります)(************f)()
AProgrammer

@AProgrammer-確かに。そしてさらに面白い例を作ることができます。
StoryTeller-Unslander Monica

この答えは確かに「何を」を説明しています。「なぜ」を追加するように改善できますか?のように、このルールの目的は何ですか?どのユースケースで改善または可能になりますか?
davidbak

2

完全な答えではなく、(コンパイルされてから)にBar入らないことを示すコードのみnamespace A。から継承する場合、この継承が入力を許可する場合A::Foo1、あいまいさのFoo違いは問題にならないことがわかります。BarA

namespace A {
    struct Foo {
        int a;
    };

    struct Foo1 {
        int a;
    };
}

struct Foo {
    int b;
};

struct Bar : public A::Foo1 {
    Bar(Foo foo) {
        c = foo.b;
    }
    int c;
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.