2013-03-22 40 views
20

此代碼編譯失敗對於g ++(Ubuntu的/ Linaro的4.6.3-1ubuntu5)4.6.3,與此錯誤預期基本表達式而不是在Microsoft編譯

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/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 ++中解釋問題的性質?

回答

42

問題是句法。您應該使用template消歧在這種情況下,讓你的成員函數模板的調用將被正確解析:

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

此消歧幫助編譯認識到接下來G.成員模板專業化而不是例如,名爲getSC的數據成員,然後是<(小於)。

template消歧的標準參考是C++ 11標準第14.2/4:

當成員模板特的名稱將出現在一個後綴表達式或之後.->後一個嵌套名稱說明符合格-ID,並且後綴表達式的對象表達式是與類型相關的或在合格-ID的嵌套名稱說明符是指一種依賴型,但是t他的名字不是當前實例化的成員(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 
} 

- 端示例]

+0

但爲什麼是不是正確地分析以開始?模棱兩可出現在哪裏? – 2013-03-22 14:13:13

+2

如果沒有'template'關鍵字,那麼一些編譯器會將類型參數列表與小於運算符混淆。 – bstamour 2013-03-22 14:15:20

+7

最醜。消歧。永遠。 – mfontanini 2013-03-22 14:18:42