Функция шаблона перегружена одинаковыми сигнатурами, почему это работает?
Минимальная программа:
#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 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.
Я использую код, подобный этому, для проекта, над которым я работаю, и я боюсь, что есть тонкое в языке, которое я не понимаю, которое вызовет некоторое неопределенное поведение в определенных случаях. Я должен также упомянуть, что он компилируется как в Clang, так и в VS11, поэтому я не думаю, что это просто ошибка компилятора.
Редактировать: исправлено второе дело (опечатка); добавлено сообщение об ошибке от Clang.
Edit # 2: Для тех из вас, кто спросил, что означает T :: type.
Изhttp://en.cppreference.com/w/cpp/types/enable_if:
шаблон <bool B, класс T = void> struct enable_if;
Если B истинно, std :: enable_if имеет открытый тип typedef, равный T; в противном случае, нет члена typedef.
enable_if - это структура. По сути, если выражение, вычисленное в первом параметре шаблона enable_if, имеет значение true (а в случае с моими примерами выше это так), тогда будет открытый членtype
имеет тот же тип, что и второй параметр шаблона.
На случай, еслиenable_if<true, int>
, enable_if :: type имеет тип int.