This code fails to compile on g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, with this error
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
but it compiles and executes correctly on Microsoft C/C++ Optimizing Compiler Version 15.00.21022.08 for 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); }
I don't understand where the problem is. Can anyone understand how to work around it, or explain the nature of the problem in g++?
The problem is syntactic. You should use the template
disambiguator in this case, so that your invocation of a member function template will be correctly parsed:
return (G.template getSC<SC<T> >().value * S.template getSC<SC<T> >().value); // ^^^^^^^^^ ^^^^^^^^^
This disambiguator helps the compiler recognizing that what follows G.
is a member template specialization and not, for instance, a data member called getSC
followed by a <
(less than).
The Standard reference for the template
disambiguator is Paragraph 14.2/4 of the C++11 Standard:
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 expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keywordtemplate
. Otherwise the name is assumed to name a non-template.[ Example: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 example ]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With