Попробуйте:
void Method1(TemplateBase<T> t)
{
t.template AsPtrTo<int>();
}
Причина в том, что компилятор не знает, какие функции-члены t
имеют во время разбора, поэтому он не знает, является ли AsPtrTo
функцией шаблона илине.Из-за этого он не может правильно проанализировать его без подсказки.
В качестве примера того, почему это необходимо, рассмотрим следующий код:
struct Foo
{
template<int N> int foo(int x) { return x + N; }
};
struct Bar
{
int foo;
};
template <typename T>
int baz(T t)
{
return t.foo<0>(1);
}
На первый взгляд выглядитвроде бы baz<Foo>
сработало бы, но baz<Bar>
не сработало бы, но все наоборот!
Подумайте, что произойдет, если я позвоню baz<Bar>
return t.foo<0>(1);
foo
является переменной-членом, поэтому, когда он видит <
, он думает, что это оператор меньше чем, поэтому он анализирует выражение следующим образом:
return (t.foo < 0) > (1);
Что является допустимым выражением (после некоторых неявных преобразований в / из bool
)!
Дело в том, что оно анализирует выражение как для Foo
, так и для Bar
, поэтому template
ключевое слово необходимо.Компиляторы должны исходить из того, что это не функция-член шаблона (если вы не добавите туда это ключевое слово).