2012-09-03 2 views
2

Я получил следующий код (не спорю о том, является ли это смысл, это всего лишь минимальный пример):C++ Compiler Странная Ошибка синтаксиса

struct X{ 
    template <typename T> 
    T foo(){ return T(); } 
}; 

template <typename T> 
struct Z{ 
    virtual X bar(){ 
     bar().foo<int>(); 
     return X(); 
    } 
}; 

Это не компилируется на моей г ++ 4.6.3 , Линия bar().foo<int>(); дает следующее сообщение об ошибке:

error: expected primary-expression before ‘int’ 
error: expected ‘;’ before ‘int’ 

, когда я первый сохранить результат бар() в локальной переменной, то она работает, то есть, если я заменю bar().foo<int>() по

 X x = bar(); 
     x.foo<int>(); 

затем он работает , Если я теперь объявить локальную переменную auto вместо X, т.е .:

 auto x = bar(); 
     x.foo<int>(); 

тогда я получаю ту же ошибку, как и раньше. Если я удалю параметр типа из класса Z (т. Е. Сделаю его обычным, а не классом шаблона), он снова будет работать.

Если я использую ClassType как X вместо int в качестве параметра типа для обув, т.е. foo<X>, то я получаю следующее сообщение об ошибке вместо:

expected primary-expression before ‘>’ token 
expected primary-expression before ‘)’ token 

Я действительно не в состоянии обнаружить ошибку здесь. Пожалуйста помоги!

+0

Компилятор кода в визуальной студии. В вашем случае я считаю, что gcc имеет ошибку :) –

+0

@ Mr.Anubis, Comeau C/C++, похоже, также скомпилирует оригинальную версию. Я тоже думаю, что это может быть ошибкой в ​​GCC. –

ответ

8

Вам необходимо оговориться, что тип в вопросе templatable (это обходное за то, что я думаю, что это ошибка в GCC см редактирования ниже), т.е.

struct X{ 
    template <typename T> 
    T foo(){ return T(); } 
}; 

template <typename T> 
struct Z{ 
    virtual X bar(){ 
     bar().template foo<int>(); 
     return X(); 
    } 
}; 

Основной вопрос должен делать с синтаксическим разбором, потому что явные шаблонные экземпляры могут быть проанализированы несколькими способами. Интересный бит (я думаю) расположен в 14.2p4, и это выглядит следующим образом:

When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object or pointer expression of the postfix-expression or the nested-name-specifier in the qualified-id depends on a template parameter (14.6.2) but does not refer to a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template . Otherwise the name is assumed to name a non-template.

Если я не сильно ошибаются, Z<T>::barделает зависит от параметра шаблона, но в то же время ссылается на текущий экземпляр, поэтому я склонен полагать, что стандарт не требует такой квалификации, как GCC. Когда несколько компиляторов имеют противоречивые результаты, я склоняюсь к Комо, который в этом случае говорит, что квалификатор template равен не обязательно.

+0

что, почему? Я никогда не видел этот синтаксис. В каких случаях я должен его использовать? И почему это приводит к такому странному поведению при использовании с 'auto'? И почему это работает, если я удаляю параметр типа из Z. Z здесь вообще не участвует! У вас есть ссылка на учебник, который объясняет все это? – gexicide

+0

это не строка 'bar(). Template foo ();' inside 'bar' member fn - бесконечная рекурсия? (хотя он компилируется), или мои глаза ничего не появляются? –

+0

@ Г-н Анубис, да. Это не неверный код. –

Смежные вопросы