функция шаблона перегрузки с одинаковыми подписями, почему это работает?


Минимальная программа:

#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;}

выход:

    1 
int foo(typename T::type search)int foo(S& search)

Почему не дает ошибку при компиляции? Когда код шаблона генерируется, не функции и имеют одинаковые подписи?

Если вы изменить функцию шаблона подписей немного, он все еще работает (как я бы ожидать, учитывая пример выше):

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");}

Но это не и но разница лишь заключается в том, что один имеет тип int подписи и определяется первым параметром шаблона.

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");}

Ошибка компилятора (лязг):

test.cpp:26:2: error: call to 'foo' is ambiguousfoo<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.

Я использую примерно такой код для проекта, Я работаю, и я боюсь, что там очень тонко, чтобы язык, который я не понимаю, что вызывает неопределенное поведение в некоторых случаях. Я должен также упомянуть, что он делает компиляции на обеих Clang и в функции vs11 так что я не думаю, что это просто баг компилятора.

Редактировать: исправлена втором случае (опечатка)

Правка #2: Для тех, кто спрашивает, Что т::Тип средства.

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

От :

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

If B is true, std::enable_if has a public member typedef type, equal to T; otherwise, there is no member typedef.

type

enable_if является struct. В принципе, если указанное выражение в качестве первого параметра шаблона enable_if это правда (а в случае моих примерах выше, это), то тогда будет публичным, что имеет тот же тип в качестве второго параметра шаблона.

enable_if<true, int>

В случае , enable_if::тип имеет тип инт.