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