Подтвердить что ты не робот

Ожидаемое первичное выражение перед ">" в ​​g++, но не в компиляторе Microsoft

Этот код не скомпилируется на g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 с этой ошибкой

test.cpp: In function ‘T mul(V&, V&)’:
test.cpp:38:27: error: expected primary-expression before ‘>’ token
test.cpp:38:29: error: expected primary-expression before ‘)’ token
test.cpp:38:53: error: expected primary-expression before ‘>’ token
test.cpp:38:55: error: expected primary-expression before ‘)’ token

но он компилируется и выполняется правильно в Microsoft C/С++ Оптимизация компилятора версии 15.00.21022.08 для x64

#include <iostream>
#include <complex>

template <class T>
class SM
{
public:
    T value;
};

template <class T>
class SC : public SM<T>
{
};

class PSSM {

public:
    template <class T>
    T & getSC() { return sc; }

private:
    SC<double> sc;
};

class USSM {

public:
    template <class T>
    T & getSC() { return sc; }

private:
    SC<std::complex<double> > sc;
};

template <class T, class V>
T mul( V & G, V & S) {
    return (G.getSC<SC<T> >().value * S.getSC<SC<T> >().value); // error is here
}


int main() {
    PSSM p;
    PSSM q;
    p.getSC<SC<double> >().value = 5; 
    q.getSC<SC<double> >().value = 3; 

    std::cout << mul<double>(p,q);

}

Я не понимаю, где проблема. Может ли кто-нибудь понять, как обойти это, или объяснить природу проблемы в g++?

4b9b3361

Ответ 1

Проблема синтаксическая. Вы должны использовать disambiguator template в этом случае, так что ваш вызов шаблона функции-члена будет правильно разобран:

return (G.template getSC<SC<T> >().value * S.template getSC<SC<T> >().value);
//        ^^^^^^^^^                          ^^^^^^^^^

Этот дизассемблер помогает компилятору распознать, что следующее G. - это спецификация шаблона члена, а не, например, элемент данных, называемый getSC, за которым следует < (меньше).

Стандартная ссылка для template disambiguator - это параграф 14.2/4 стандарта С++ 11:

Когда имя специализации шаблона члена появляется после . или -> в постфиксном выражении или после вложенного имени-спецификатора в идентификаторе с квалификацией, а выражение объекта postfix-expression - это тип -зависимый или специфицированный вложенным именем-идентификатор в identified-id относится к зависимому типу, но имя не является членом текущего экземпляра (14.6.2.1), имя шаблона члена должно быть префиксным по ключевому слову template. В противном случае предполагается, что имя называется не-шаблоном. [Пример:

struct X {
template<std::size_t> X* alloc();
template<std::size_t> static X* adjust();
};
template<class T> void f(T* p) {
T* p1 = p->alloc<200>(); // ill-formed: < means less than
T* p2 = p->template alloc<200>(); // OK: < starts template argument list
T::adjust<100>(); // ill-formed: < means less than
T::template adjust<100>(); // OK: < starts template argument list
}

-end пример]