通用的swap可以在stl裡找到:
namespace std }
有很多類使用pimpl來分離實現與介面,對它們的swap要慎重。
class widgetimpl ; class widget ... private: widgetimpl *pimpl; };
其實,swap只要交換二者的指標即可,不用拷貝裡面的資料:
void widget::swap(widget& other) namespace std }
stl裡的容器都是這樣實現swap的。
現在假設widget和widgetimpl都是模板類,即:
templateclass widget ; templateclass widgetimpl ;
那麼,如何實現swap呢?下面這樣的思路可以嗎:
namespace std }
實際上,對模板函式的定義進行「partial specialization」在c++中是無效的。如果編譯通過,說明編譯器有問題。
不過,對模板類,可以進行「partial specialization」。
那麼,過載swap可以解決問題嗎:
namespace std }
但是,std這個名字空間,是不適合用上面的方法解決問題的。這屬於對std空間增加了新的模板類。
而std空間的內容,只有c++委員會才有權決定。
可能上面的**在一些編譯器上可以正常執行,比如vc,但實際上屬於「未定義行為」!
需要稍稍改一下:
namespace widgetstuff ; // member function ... templatevoid swap(widget& a, widget& b) }
把swap移到新的名字空間了。那麼,像下面的**:
using widgetstuff::widget; widgetw; widgetw2; swap(w, w2);
c++將應用argument-dependent lookup (koenig lookup)規則,進行查詢,最後找到以widget作為引數的swap函式。
從客戶的角度看下面的**:
templatevoid dosomething(t& obj1, t& obj2)
哪乙個swap會被呼叫到呢?有可能是std裡的通用版本;有可能是std裡完全特化的版本;有可能是在某個名字空間裡的過載版本。
如果你想讓它呼叫過載版本,當過載版本不存在,就呼叫std通用版本,那麼可以像下面這樣寫:
templatevoid dosomething(t& obj1, t& obj2)
Item 25 考慮實現乙個不拋異常的swap
swap 函式最初由 stl 引入,已經成為異常安全程式設計的關鍵函式,同時也是解決自賦值問題的通用機制。std 中它的基本實現是很直觀的 namespace std 可以看到,上述 swap 是通過賦值和拷貝構造實現的。所以 std swap 並未提供異常安全,但由於 swap 操作的重要性,我們...
討論 日誌出錯了,應不應該丟擲錯誤
最近一直在想,業務日誌出錯了,應不應該丟擲錯誤?例如以下 12 3shop.addproduct 4log.writelog 新增了一件新商品,物品名為xx,xx 5 public class log 如果log.writelog出現了錯誤,應該丟擲錯誤嗎?若丟擲錯誤,便可以及時發現錯誤,並處理.但...
討論 日誌出錯了,應不應該丟擲錯誤
最近一直在想,業務日誌出錯了,應不應該丟擲錯誤?例如以下 12 3shop.addproduct 4log.writelog 新增了一件新商品,物品名為xx,xx 5 public class log 如果log.writelog出現了錯誤,應該丟擲錯誤嗎?若丟擲錯誤,便可以及時發現錯誤,並處理.但...