Função de template sobrecarregando com assinaturas idênticas, por que isso funciona?

Programa mínimo:

#include <stdio.h>

#include <type_traits>

template<typename S, typename T>
int foo(typename T::type s) {
    return 1;
}

template<typename S, typename T>
int foo(S s) {
    return 2;
}

int main(int argc, char* argv[]) {
    int x = 3;
    printf("%d\n", foo<int, std::enable_if<true, int>>(x));

    return 0;
}

saída:

    1 

Por que isso não dá um erro de compilação? Quando o código do modelo é gerado, as funções nãoint foo(typename T::type search) eint foo(S& search) tem a mesma assinatura?

Se você alterar as assinaturas de função de modelo um pouco, ele ainda funciona (como eu esperaria dado o exemplo acima):

template<typename S, typename T>
void foo(typename T::type s) {
    printf("a\n");
}

template<typename S, typename T>
void foo(S s) {
    printf("b\n");
}

No entanto, isso não acontece e, no entanto, a única diferença é que um tem uma assinatura int e o outro é definido pelo primeiro parâmetro do modelo.

template<typename S, typename T>
void foo(typename T::type s) {
    printf("a\n");
}

template<typename S, typename T>
void foo(int s) {
    printf("b\n");
}

Erro do compilador (Clang):

test.cpp:26:2: error: call to 'foo' is ambiguous
foo<std::enable_if<true, int>>(3);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:16:6: note: candidate function [with T = std::__1::enable_if<true, int>]
void foo(typename T::type s) {
        ^
test.cpp:21:6: note: candidate function [with T = std::__1::enable_if<true, int>]
void foo(int s) {
        ^
1 error generated.

Eu estou usando código semelhante a este para um projeto que estou trabalhando e eu tenho medo de que há um sutilmente para a linguagem que eu não estou entendendo que causará algum comportamento indefinido em certos casos. Eu também devo mencionar que ele compila tanto no Clang quanto no VS11, então eu não acho que seja apenas um bug do compilador.

Edit: Corrigido segundo caso (typo); adicionou mensagem de erro de Clang.

Edit # 2: Para aqueles que perguntaram o que T :: type significa.

Dehttp://en.cppreference.com/w/cpp/types/enable_if:

template <bool B, classe T = void> struct enable_if;

Se B for true, std :: enable_if tem um tipo typedef de membro público, igual a T; caso contrário, não há nenhum membro typedef.

enable_if é uma estrutura. Basicamente, se a expressão avaliada no primeiro parâmetro de template de enable_if for true (e, no caso dos meus exemplos acima, é), então haverá um membro públicotype que tem o mesmo tipo que o segundo parâmetro de modelo.

No caso deenable_if<true, int>, enable_if :: type tem um tipo de int.

questionAnswers(2)

yourAnswerToTheQuestion