Nome do atributo confuso em C ++ para o modelo de membro

Descobri que ao acessar um atributo não modelo (v.foo) de uma variável de um tipo de modelo (T& v), C ++ pode ser induzido a pensar que é um modelo de membro se houver uma função de modelo com o mesmo nome (template class <T> void foo()). Como isso pode ser explicado a partir da especificação do C ++? Considere este programa simples:

#include <cassert>

/** Determine whether the 'foo' attribute of an object is negative. */
template <class T>
bool foo_negative(T& v)
{
    return v.foo < 0;
}

struct X
{
    int foo;
};

int main()
{
    X x;
    x.foo = 5;
    assert(!foo_negative(x));
    return 0;
}

Nós temos uma função de modelofoo_negative que toma um objeto de qualquer tipo e determina se seu atributo foo é negativo. omain função instanciafoo_negative com [T = X]. Este programa compila e executa sem qualquer saída.

Agora, adicione essa função ao topo do programa:

template <class T>
void foo()
{
}

Compilando-o com o G ++ 4.6.3 resulta neste erro do compilador:

funcs.cpp: In function ‘bool foo_negative(T&)’:
funcs.cpp:13:14: error: parse error in template argument list
funcs.cpp: In function ‘bool foo_negative(T&) [with T = X]’:
funcs.cpp:25:5:   instantiated from here
funcs.cpp:13:14: error: ‘foo’ is not a member template function

(Onde a linha 13 éreturn v.foo < 0 e a linha 25 éassert(!foo_negative(x)).)

Clang produz erros semelhantes.

Wat? Como a adição de uma função não relacionada que nunca é chamada gerencia introduzir um erro de sintaxe em um programa válido? Ao analisarfoo_negative, o compilador não sabe o tipo deve, crucialmente, não sabe sev.foo é um modelo de membro ou um membro regular. Aparentemente, ele tem que decidir no momento da análise (antes do modelo ser instanciado) se deve tratá-lo como um modelo de membro ou um membro regular.

Se pensav.foo é um modelo de membro, então< 0 é visto como passando0 como um argumento de modelo, e há uma falta>, daí o erro de sintaxe. Então quandofoo_negative é instanciado com [T = X], há outro erro porqueX::foo não é um modelo de membro.

Mas por que pensav.foo é um modelo de membro? Essa ambiguidade é precisamente o quetemplate palavra-chave é para: se eu escreviv.template foo, então eu estaria explicitamente dizendo C ++ para esperar um modelo de membro, mas eu não usei otemplate palavra chave! Eu não me referi a um modelo de membro, por isso deve assumir que é um membro regular. O fato de que há umfunção do mesmo nome que o membro não deve ter qualquer efeito. Por que isso? Não pode ser um bug no compilador porque o GCC e o clang são consistentes.

questionAnswers(3)

yourAnswerToTheQuestion