A pesquisa de nome e a resolução de sobrecarga são diferentes. O nome deve ser encontrado em um escopo primeiro, ou seja, precisamos encontrar um X
para que o nome do_stuff
seja resolvido para X::do_stuff
- independentemente do uso do nome - e, em seguida, a resolução de sobrecarga selecione entre as diferentes declarações de X::do_stuff
.
O processo não é identificar todos esses casos A::do_stuff
, B::do_stuff
etc., que são visíveis, e depois executar a resolução de sobrecarga entre a união do que isso. Em vez disso, um único escopo deve ser identificado para o nome.
Neste código:
struct Baz : public Foo, public Bar
{
void func ()
{
do_stuff (1.1f); // ERROR HERE
}
};
Baz
não contém o nome do_stuff
, portanto, as classes base podem ser consultadas. Mas o nome ocorre em duas bases diferentes, portanto, a pesquisa de nome falha ao identificar um escopo. Nunca chegamos a uma resolução de sobrecarga.
A correção sugerida na outra resposta funciona porque introduz o nome do_stuff
no escopo de Baz
e também introduz 2 sobrecargas para o nome. Portanto, a pesquisa de nome determina o que do_stuff
significa Baz::do_stuff
e, em seguida, a resolução de sobrecarga seleciona as duas funções conhecidas como Baz::do_stuff
.
Além disso, o sombreamento é outra consequência da pesquisa de nome (não uma regra em si). A pesquisa de nome seleciona o escopo interno e, portanto, qualquer coisa no escopo externo não corresponde.
Um outro fator complicador ocorre quando a pesquisa dependente de argumento está em jogo. Para resumir muito brevemente, a pesquisa de nome é feita várias vezes para uma chamada de função com argumentos do tipo de classe - a versão básica, conforme descrito na minha resposta, e novamente para o tipo de argumento. Em seguida, a união dos escopos encontrados entra no conjunto de sobrecargas. Mas isso não se aplica ao seu exemplo, pois sua função possui apenas parâmetros do tipo interno.