日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++模板专门化与重载

發(fā)布時間:2023/12/10 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++模板专门化与重载 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  最近在復(fù)習(xí)C++有關(guān)知識,又重新看<<Effective C++>>,收獲頗豐。原來以前看這邊書,好多地方都是淺嘗輒止。<<Effective C++>>條款25:考慮寫出一個不拋出異常的swap函數(shù),涉及到C++模板專門化(Templates?Specialization)和函數(shù)重載(overloading)問題,而當(dāng)重載與模板攪合在一起時,許多問題都變得“模棱兩可”。

  首先回顧<<Effective C++>>條款25:考慮寫出一個不拋出異常的swap函數(shù),想告訴我們什么東西。

  swap函數(shù)為我們提供了異常安全編程的方法,以及用來作為處理自我賦值一種常見機(jī)制,因此實(shí)現(xiàn)一個不拋出異常的swap函數(shù),變得相對重要起來。缺省情況下的swap函數(shù)的典型實(shí)現(xiàn)如下:

namespace std {template<typename T>void swap(T& a, T& b){T temp(a);a = b;b = temp; } }

  然后,對于模型數(shù)據(jù)類型其成員變量是指針,指向一個對象,保存了數(shù)據(jù)(pointer to implementation手法)。如果copying函數(shù)采用了deep copying方法,上面的代碼將會非常低效,因?yàn)?#xff0c;只需要互換a與b指針即可。問題是,缺省版本swap對類型無法可知這些信息,因此針對上述情況,需要專門化swap函數(shù)。

  1)如果T是class,可以先讓T提供一個swap函數(shù),完成swap功能,然后借由functhon template的全特化,實(shí)現(xiàn)專門化的swap函數(shù):

class Widge { public:void swap(Wiget& other){using std::swap();swap(pImpl, other.pImpl);}

private: WidetImpl* pImpl;
};

//為程序提供一個特化版本的swap: namespace std
{
  
template<>
  void swap<Widegt>(Widget& a, Widget& b)
  { a.swap(b);
  
}
}

  上面的代碼很好的與STL容器保持了一致性,因?yàn)镾TL容器也都提供了swap成員函數(shù)和std::swap特化版本。

  2)如果Widget與WidgetImpl不是class,而是class template,特化版本的swap函數(shù),我們可能想寫成這樣的形式:

namespace std {template<class T>void swap<Widegt<T>>(Widget<T>& a, Widget<T>& b) {a.swap(b);} }

  然而這個代碼卻無法通過編譯,C++不支持function template的偏特化,我們需要使用模板函數(shù)的重載技術(shù):

namespace std {template<class T>void swap( Widget<T>& a, Widget<T>& b) //重載了function templates {a.swap(b);} }

  問題似乎已經(jīng)解決了,嗯,是的,還存在一個問題:用戶可以全特化std內(nèi)的templates,但是不能新的對象(template、function、class)。解決方法是將這些類與swap函數(shù)放到新的命名空間中,這邊便獨(dú)立與std命名空間。

--------------------------------------------------------------------華麗分割線--------------------------------------------------------------------

  上面介紹的內(nèi)容,涉及到以下的內(nèi)容:1)模板函數(shù);2)重載函數(shù);3)全特化和偏特化。當(dāng)這些東西交織在一起的時候,我們需要足夠的耐心做區(qū)分甄別。

  1)模板類、模板函數(shù)與重載

  // Example 1: Class vs. function template, and overloading //// A class templatetemplate<typename T> class X { /*...*/ }; // (a) 類模板// A function template with two overloadstemplate<typename T> void f( T ); // (b) 函數(shù)模板 template<typename T> void f( int, T, double ); // (c) 函數(shù)模板重載

  (a)、(b)、(c)均沒有專門化,這些未被專門化的template又被稱為基礎(chǔ)基模板。

  2)特化

  template class可以有全特化與偏特化兩種, template function僅能全特化。

// Example 1, continued: Specializing templates // // A partial specialization of (a) for pointer types template<typename T> class X<T*> { /*...*/ }; // A full specialization of (a) for int template<> class X<int> { /*...*/ };// A separate base template that overloads (b) and (c) // -- NOT a partial specialization of (b), because // there's no such thing as a partial specialization // of a function template! template<class T> void f( T* ); // (d)// A full specialization of (b) for int template<> void f<int>( int ); // (e)// A plain old function that happens to overload with // (b), (c), and (d) -- but not (e), which we'll // discuss in a moment void f( double ); // (f)

  當(dāng)function template與重載攪合在一起的時候,就存在匹配哪個版本函數(shù)的問題,匹配規(guī)則如下:

  1)首先查找non template function ,如果在這些函數(shù)中匹配成功,則匹配結(jié)束(first-class citizens)

  2)否定,在base template function 中查找最匹配的函數(shù),并實(shí)例化,如果base template function恰巧有提供全特化版本模板函數(shù),則使用全特化版本(sencond-class citizens)

?將以上兩個規(guī)則運(yùn)用的例子:

// Example 1, continued: Overload resolution // bool b; int i; double d;f( b ); // calls (b) with T = bool f( i, 42, d ); // calls (c) with T = int f( &i ); // calls (d) with T = int f( i ); // calls (e) f( d ); // calls (f)

  最后一個問題:如何判斷哪個base template function被specialization,再看下面的例子:

// Example 2: Explicit specialization // template<class T> // (a) a base template void f( T );template<class T> // (b) a second base template, overloads (a) void f( T* ); // (function templates can't be partially // specialized; they overload instead) template<> // (c) explicit specialization of (b) void f<>(int*);// ...int *p; f( p ); // calls (c)

  c是b是全特化,f(p)將會調(diào)用,符合人們的一般想法,但是,如果置換b與c的順序,結(jié)果就不那么一樣了:

// Example 3: The Dimov/Abrahams Example // template<class T> // (a) same old base template as before void f( T );template<> // (c) explicit specialization, this time of (a) void f<>(int*);template<class T> // (b) a second base template, overloads (a) void f( T* );// ...int *p; f( p ); // calls (b)! overload resolution ignores // specializations and operates on the base // function templates only

  這個時候,c將是a的全特化(編譯器沒看到后面的b的定義)。按照配對規(guī)則,首先查找base template function最適合匹配的,b正好最為匹配,并且沒有全特化版本,因此將會調(diào)用b。

  重要準(zhǔn)則:

  1)如果我們希望客戶化base template function,直接利用傳統(tǒng)的函數(shù)形式,如果使用重載形式,那么請不要提供全特化版本。

  2)如果正在編寫一個base template function,不要提供特化和重載版本,將客戶化定制功能下放給用戶。實(shí)現(xiàn)方法是,在class template 同static 函數(shù)接口:

// Example 4: Illustrating Moral #2 // template<class T> struct FImpl;template<class T> void f( T t ) { FImpl<T>::f( t ); } // users, don't touch this! template<class T> struct FImpl { static void f( T t ); // users, go ahead and specialize this };

  準(zhǔn)則2的動機(jī)就是利用class template 特化與偏特化功能實(shí)現(xiàn)function 特化與偏特化功能。

?

參考文獻(xiàn):

<<Effective C++>>, Scott Meyers

<<Why Not Specialize Function Templates?>>,??C/C++ Users Journal, 19(7), July 2001

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

    

?

轉(zhuǎn)載于:https://www.cnblogs.com/wangbogong/p/3249238.html

總結(jié)

以上是生活随笔為你收集整理的C++模板专门化与重载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。