這個問題其實之前我已經問過,但當時我對這段代碼理解有誤,只想著能編譯就行。
代碼如下:
template <class T>
inline void AssertMoveable0(T *t) { AssertMoveablePtr(&**t, *t); }
template <class T, class B = EmptyClass>
struct Moveable : public B {
friend inline void AssertMoveable0(T *) {}//這里出錯
};
這段代碼的效果是不是Moveable的子類在呼叫AssertMoveable0將不能通過編譯,
在gcc和vc下都能編譯通過,
在cb下改成friend inline void AssertMoveable0<T>(T *);也能通過編譯,但就沒了這種效果。
改成 friend template<> inline void AssertMoveable0<T>(T *){}就是E2141 Declaration syntax error。
追根結底想來就是cb中的友元模板函式偏特化應該怎么寫,或都說cb支不支持友元模板函式偏特化。
有沒有人知道答案的。
uj5u.com熱心網友回復:
這個,你問的也太高端了。uj5u.com熱心網友回復:
template<class T> void AssertMoveable0(T *);//宣告AssertMoveable0是一個函式模板//--------
template <class T, class B = EmptyClass>
struct Moveable : public B {
friend inline void AssertMoveable0<>(T *) {}//宣告模板AssertMoveable0 是友元
//friend inline void AssertMoveable0<T>(T *) {}//宣告模板特化,這樣用也行吧。
};
//--------
函式模板的具體實作,這里就可以呼叫類中的私有成員了。
template<class T> void AssertMoveable0(T *)
{
...
}
即要先宣告一個函式模板,然后指定該模板函式是友元,最后才是函式模板的實作。
至于你說的那個效果,上面代碼中看不出來。
模板語法的支持各個編譯器略有差異,試試吧,不過最好別用B6試。
uj5u.com熱心網友回復:
不能通過編譯。
還是卡在這個友元函式上,實際上的效果就是為每一個支持moveable的類特化一個 AssertMoveable0函式,這個函式不做其它事,只是能通過編譯,沒經過特化的型別會呼叫那個肯定不能編譯的函式AssertMoveable0(T *t) { AssertMoveablePtr(&**t, *t); },然后出錯。
uj5u.com熱心網友回復:
friend inline void AssertMoveable0(T *) {}//這里如果用 {} ,那么友元函式就在這里定義,{}中可以寫上函式代碼,如果用" ; "結束,友元函式就在外部定義。 在這里用{}定義友元函式是不屬于類的成員的。你代碼中在外面定義了,所以該用" ; "結束 . 因為你的友元函式要使用類的成員,所以在外面定義的話,最好是先宣告,然后將函式模板實作在類定義的后面。
要看你是怎么呼叫的 AssertMoveable0(T *) ;
Moveable<int , EmptyClass> A ;
AssertMoveable0(&A);
如果是象上面那樣呼叫,那么友元該這樣定義:
template <class T, class B = EmptyClass>
struct Moveable : public B {
friend inline void AssertMoveable0(Moveable<T,B> *);
};
你的代碼太少,不知道你是如何呼叫的。
uj5u.com熱心網友回復:
ppower,你前面說的前置宣告模板函式然后在最后實作的方法應該是bcb6中能行得通。但我現在用的是xe4(也因為是xe4我才用回delphi或者說delphi的同伴cb的),所以不可能找回bcb6來裝的。
其實這個模板的作用是因為自己接手記憶體管理,其中有些型別是可以簡單申請復制的,為不能這么做的型別進行編譯期檢測以防出錯。
最后的使用型式是這樣的:
template<class T>
class CT:Moveable< CT<T> >{
}
AssertMoveable0(CT*);
這時會呼叫這個類從Moveable< CT<T> >中實作的友元AssertMoveable0(CT<T> *) {}這樣可以順利通過編譯。
uj5u.com熱心網友回復:
特意在XE4 32位版本,測驗了一下,以下通過編譯。64位版本是據說是使用Clang編譯的,應該也能通過。
class EmptyClass{};
template <typename T , typename B = EmptyClass >
class Moveable : public B {
friend void AssertMoveable0(Moveable<T,B> *a) {}
};
template<class T> class CT: public Moveable< CT<T> >{};
//測驗:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
CT<int> A ;
AssertMoveable0(&A);
//AssertMoveable0(this);//這行通不過編譯。
}
uj5u.com熱心網友回復:
友元函式模板,讓一個函式模板的所有函式都成為一某個類的友元:class EmptyClass{};
template <typename T> void AssertMoveable0 (T *) ; //先宣告一個函式模板
template <typename T , typename B = EmptyClass >
class Moveable : public B {
friend void AssertMoveable0<T>(T *) ; //這里宣告該模板的函式都是友元
void Test() {}
public :
};
template <typename T>
void AssertMoveable0 (T *a) { a->Test();} //最后是該模板的實作
template<class T> class CT: public Moveable< CT<T> >{};
void __fastcall TForm1::FormCreate(TObject *Sender)
{
CT<int> A ;
AssertMoveable0(&A);
}按樓主的使用要求,明顯,這種用法比不上在類模板內部定義友元函式的方式。
原因在于出錯時提示不夠人性化。
uj5u.com熱心網友回復:
偏特化...是侯傑取的嗎? 原本特化(Specialization) 就讓人看得一頭霧水的...偏特化 : 英文為 Partial Specialization...這 Template(模板|範本) 裡的專用術語名詞翻譯得有點怪...直接看英文還比較容易理解且直覺...或翻成白話一點之部分特別化或區域特殊化明瞭~uj5u.com熱心網友回復:
泛型:泛指任意一種資料型別特化: 只針對指定的資料型別 , 這個指定的資料型別又可以是一系列型別(模板類或模板函式)
偏特化: 存在多個模板引數時,部分引數特化,部分引數保持泛型,這樣給一個偏特化的名稱出來,意思是并非全部特化,我也覺得畫蛇添足。
模板類(這是一個類,是通過模板生成的類)
類模板(這是一個模板,可以生成類)
的這類名稱可以體現漢字的優美,偏特化則起名不好,偏取其不是全部的意思,但這里沒必要用“偏”這個有其他歧義的字。
uj5u.com熱心網友回復:
這裡我先幫 C++ Builder 申冤澄清一下...其實在 3.0 版時對於模板友元架構已建置完成...後來在 4.0 又追加一項模板類實體的友元使之完整~ 那為什麼 VC 與 GCC 可以編譯通過而 C++ Builder 卻不行呢? 應該說 C++ Builder 對於編程語法比較嚴謹而 VC 與 GCC 則比較寬鬆~沒那麼複雜也不高端啦~ 其實樓主的問題與模板類或模板類的友元模板函數偏特化皆無關...只是疏忽了編程上先後順序的淺規則而以~
class EmptyClass{};
//---------------------------------------------------------------------------
template <class T, class B = EmptyClass>
struct Moveable : public B {
friend inline void AssertMoveable0(T *) {}
};
//---------------------------------------------------------------------------
template <class T>
inline void AssertMoveable0(T *t) {AssertMoveablePtr(&**t, *t);}
uj5u.com熱心網友回復:
PPower 大哥您講解得清清楚楚...小弟著實佩服著!

這偏特化一詞看得我都偏頭痛了起來...真希望外文譯者若想不出貼切的名詞...乾脆以白話翻譯加上外文註解...這樣才不會搞了一堆莫名的怪術語嚇退許多初學者呀!
uj5u.com熱心網友回復:
@PPower 感覺大哥好厲害 佩服轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/90190.html
標籤:基礎類
上一篇:c++ builder 里模板類的友元函式,vc能編譯過,c++builder編譯錯誤, 求教
下一篇:miracl庫函式呼叫問題求助
