使用"使用"两次由不同的编译器进行不同的解释

Jor*_*tao 15 c++ c++11

请考虑以下代码:

struct A {
    int propose();
};

struct A1 : A {
    int propose(int);
    using A::propose;
};

struct B1 : A1 {
protected:
    using A1::propose;
public:
    using A::propose;
};

int main() {
    B1().propose();
}
Run Code Online (Sandbox Code Playgroud)

让我们编译一下:g++ -std=c++11 main.cpp.

我使用GNU 4.8.1得到以下编译器错误:

main.cpp: In function 'int main()':                                                                                                                    
main.cpp:2:9: error: 'int A::propose()' is inaccessible
     int propose();
         ^
main.cpp:18:18: error: within this context
     B1().propose();
Run Code Online (Sandbox Code Playgroud)

但是,此代码在AppleClang 6.0.0.6000056中编译.

我明白没有必要using进入B1,(在我的代码中是必要的,但我using错误地得到了1 ).无论如何,为什么Clang编译呢?这是预期的吗?

Bar*_*rry 11

在[namespace.udecl]中,我们有:

using声明将基类中的名称带入派生类范围时,派生类中的成员函数和成员函数模板将覆盖和/或隐藏具有相同名称的成员函数和成员函数模板,parameter-type-list(8.3 0.5),CV-资格,和ref-限定符(如果有的话)在一个基类(而不是相互矛盾的).

标准明确指出引入的名称不会与类中的名称冲突.但它没有提到引入相互冲突的名字.

该部分还说:

using声明是声明的,因此可以反复使用,其中(并且仅在哪里)多个声明是允许的.[例如:

struct B {
    int i;
};

struct X : B {
    using B::i;
    using B::i; // error: double member declaration
};
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

有趣的是,在下面的例子中,GCC很乐意编译它(并打印A),而Clang允许构造一个C但拒绝对foo的调用是不明确的:

struct A {
    void foo() { std::cout << "A\n"; }
};

struct B {
    void foo() { std::cout << "B\n"; }
};

struct C : A, B {
    using A::foo;
    using B::foo;
};


int main()
{
    C{}.foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以简短的回答是 - 我怀疑标准中没有说明这一点,并且两个编译器都在做可接受的事情.我会避免为了一般的理智而编写这种代码.