template<class T> void f(T,
typename size_map<sizeof(&U::foo)>::type* = 0);
Это не работает, потому что U
не участвует в удержании.Хотя U
является зависимым типом, при выводе для f
он обрабатывается как фиксированный тип, записанный с независимым именем.Вам необходимо добавить его в список параметров f
/* fortunately, default arguments are allowed for
* function templates by C++0x */
template<class T, class U1 = U> void f(T,
typename size_map<sizeof(&U1::foo)>::type* = 0);
Так что в вашем случае, поскольку U::foo
не зависит от параметров самого f
, вы получаете ошибку при неявном создании экземпляра S<X>
(попробуйте закомментировать звонок, и он все равно должен потерпеть неудачу).FCD говорит по адресу 14.7.1/1
Неявное создание экземпляра специализации шаблона класса вызывает неявное создание экземпляров объявлений, но не определений или аргументов по умолчанию, функций-членов класса, классов-членов,члены статических данных и шаблоны элементов;
То есть, если вы неявно создадите экземпляр S<X>
, будет создано следующее объявление шаблона функции
template<class T> void S<X>::f(T,
typename size_map<sizeof(&X::foo)>::type* = 0);
Анализ этого объявления шаблона будетобнаружите, что он не может разрешить ссылку на X::foo
и выдает ошибку.Если вы добавите U1
, объявление шаблона еще не будет пытаться разрешить ссылку на U1::foo
(поскольку U1
является параметром f
), и, таким образом, останется действительным и SFINAE при попытке f
называться.