Por que os qualificadores de nome de classe redundante são permitidos?

Eu me deparei com algum código como este:

struct A {
    A() {}
    A(int) {}
};

struct B : A {
    void init(int i);
};

void B::init(int i) {
    A::A(i); // what is this?
}

int main() {
    B b;
    b.init(2);
}

Isso compilou e executou usando o VC11 beta sem erros ou avisos com / W4.

A intenção aparente é chamar B :: init para reinicializar o subobjeto base A do B. Eu acredito que realmente analisa como uma declaração de variável para uma nova variável chamadai com tipoA. Compilar com clang produz diagnósticos:

ConsoleApplication1.cpp:11:14: warning: declaration shadows a local variable
        A::A(i);
             ^
ConsoleApplication1.cpp:10:22: note: previous declaration is here
    void B::init(int i) {
                     ^
ConsoleApplication1.cpp:11:14: error: redefinition of 'i' with a different type
        A::A(i);
             ^
ConsoleApplication1.cpp:10:22: note: previous definition is here
    void B::init(int i) {
                     ^

Parece curioso que o tipo possa ser referido com a qualificação de classe redundante.

Além disso,A::A(i) parece ser analisado diferentemente pelo VS11 e pelo clang / gcc. Se eu fizerA::A(b) clang e gcc criam uma variávelb do tipoA usando o construtor padrão. Erros VS11 fora nesse dizendob é um identificador desconhecido. VS11 parece analisarA::A(i) como a criação de um temporárioA usando o construtorA::A(int) comi como o parâmetro. Quando o qualificador redundante é eliminado, o VS analisa a fonte como uma declaração de variável, como clang e gcc, e produz um erro semelhante sobre o sombreamento da variáveli.

Essa diferença na análise explica por que o VS11 vai sufocar em mais de um único qualificador extra;A::A::A::A(i)e por que, dado que clang e gcc podem aceitar um qualificador extra, qualquer número mais de um extra tem o mesmo resultado que um extra.

Aqui está outro exemplo com os qualificadores redundantes em um contexto diferente. Todo compilador parece analisar isso como uma construção temporária:

class Foo {};

void bar(Foo const &) {}

int main() {
    bar(Foo::Foo());
}
Por que os qualificadores redundantes são permitidos?Existem alguns contextos nos quais os construtores podem ser referenciados, como a sintaxe para os construtores herdados (class D : B { using B::B; };), mas VS parece estar permitindo isso em qualquer lugar. O VS está errado e o clang e o gcc estão certos em como os qualificadores redundantes são analisados?Eu sei VS ainda é um pouco atrás em termos de conformidade com os padrões, mas eu acho um pouco surpreendente que compiladores modernos, ativamente desenvolvidos poderiam ser tão divergentes, neste caso, resolvendo um qualificador redundante como o nome de um construtor (embora construtores não têm nomes) vs. resolvendo qualificadores redundantes simplesmente para o tipo, resultando em VS construindo um temporário onde os outros declaram uma variável. Pode ser ainda pior ondeB b(A::A(i)); é analisado por clang e gcc como a análise mais vexatória, mas VS a vê como declarando uma variávelb do tipoB com um inicializador. Ainda existem muitas diferenças tão graves?Claramente, os qualificadores redundantes devem ser evitados no código portátil. Existe uma boa maneira de evitar que essa construção seja usada?

questionAnswers(2)

yourAnswerToTheQuestion