O que eu digo abaixo (no OLD POST ) deve ser verdadeiro até certo ponto, mas o problema real é que SFINAE é usado incorretamente; portanto, não tenho mais tanta certeza de que isso seja um bug no gcc.
Uma declaração de alias deve sempre ter êxito, você não pode SFINAE lá, pois não é uma declaração ou especialização de classe ou função (isso faz sentido, pois você não pode se especializar em alias). Se a declaração do alias não for bem-sucedida, o programa está mal formado. Portanto, o compilador pode assumir que nunca ocorrerá caso a declaração de alias não seja bem-sucedida até que você o force a instanciar esse modelo.
Portanto, é perfeitamente aceitável para o compilador pensar que sfinae_v_t<T,...>
é sempre T
, uma vez que isso acontecerá, quando o programa não estiver mal formado. Portanto, verá que, em todos os casos em que o programa não está mal formado, a especialização parcial não se especializa e, como tal, dirá que isso está mal formado. (Isso é o que clang faz).
Eu não acho que o compilador seja forçado a fazer isso. E se não, e apenas pensa "Ok, sfinae_v_t
é algum tipo, qualquer que seja.", Então não é óbvio que isso seja uma redeclaração. Então, acho que até instanciarmos um deles, não há nada errado em não lançar um erro.
Mas quando a instanciamos, deve haver o problema que temos uma redeclaração ou que o programa está mal formado devido std::enable_if
, dependendo do argumento do modelo. O GCC deve escolher pelo menos um deles, mas não o faz.
Isso também não se aplica absolutamente ao exemplo mais fácil sem std::enable_if
. Por isso, ainda acho que isso é um bug no GCC, mas estou suficientemente impressionado que não posso mais dizer isso com certeza. Eu diria apenas que alguém deveria relatar isso como um bug e deixar as pessoas do gcc pensarem sobre isso.
POSTO ANTIGO
Este é um erro no gcc. O padrão nos fornece regras para converter um modelo de classe em modelos de função. Um modelo de classe é mais especializado que outro se sua função vier antes da outra na ordem parcial do modelo de função.
Eu criei as funções aqui e agora o gcc afirma que chamá-las é ambígua, portanto, também seria necessário dizer que os modelos de classe são igualmente especificados.
Nota: Lendo o padrão cuidadosamente, o compilador na minha cabeça concorda com o clang.