2010-02-10 80 views
9

爲了測試並顯示我的函數庫的一些函數的結果,我創建了一組方便的函數。重載全局類型轉換運算符

我有一個execute功能,看起來像:

template <typename R, typename I> 
std::string execute(const std::string& func_name, R(*func_ptr)(const I&), const I& func_input); 

它調用的函數,並顯示在一個格式化字符串,我可以向std::cout結果和參數。

問題是,我的一些功能不返回可轉換爲字符串結果。我以爲我可以簡單的東西,如超載全球::operator std::string

template <typename T> 
operator std::string(const std::vector<T>& v); 

但是GCC抱怨:

error: 'operator std::string(const std::vector<T, std::allocator<_CharT> >&)' must be a nonstatic member function 

嘛,當然問題是,我不能成員運營商加入到std::vector,連服我的班級,我不想污染他們「測試」轉換運營商。

我想我可以添加一個間接層並使用函數而不是轉換操作符,但那不是更美觀的解決方案。我也可以爲std::ostream重載::operator <<並使用std::ostringstream,但這也不是最乾淨的解決方案。

我想知道全局轉換運算符是否真的不可重載,如果有,爲什麼。

回答

10

轉換運算符(演員操作符)必須是生成轉換類型的轉換類的成員。作爲賦值運算符,它們必須是成員函數,正如編譯器告訴你的那樣。

根據您想要在調試部分投入多少努力,您可以嘗試使用元編程將您的執行方法轉發給不同的實際實現,爲將打印內容的容器提供特定的實現方法。

爲什麼你不想爲你的類型提供operator<<?我認爲這實際上是一種慣用的解決方案。不像您使用轉換爲字符串產生打印結果的方法,在C++中慣用的方式與其他語言中提供operator<<,然後使用stringstreams(或boost::lexical_cast或一些類似的解決方案)轉換爲基於該operator<<執行字符串。有一個簡單的工具類here從,如果你想使用一個起點重寫operator<<元素創建string

1

沒有用戶定義的全局轉換運算符。您必須控制目標類型(在這種情況下,非顯式的一個參數構造函數是轉換運算符)或源類型(在這種情況下,您必須重載成員運算符target())。

4

我想知道全局轉換運算符是否真的不可重載,如果有,爲什麼。

不,沒有這樣的事情。轉換函數必須是類的成員。如果不是這樣,那麼通過引入含糊不清,它會使重載問題成爲編譯器特別棘手的問題。

+1

但是許多運營商都可以作爲全局或成員,何樂不爲呢?例如,如果有一個全局和成員操作符<<,編譯器會抱怨模糊的調用,它可能會對convertions做同樣的事情。 – NewbiZ 2010-02-10 08:12:38

+2

轉換函數是特殊的成員函數(因爲是構造函數,析構函數,OP =和拷貝構造),因爲它們參與轉化/對象創建。見12.3。 – dirkgently 2010-02-10 08:17:23

0

轉換函數必須是成員函數。該函數可能不指定返回類型,並且參數列表必須爲空。應該謹慎地使用它們,並且應該有從一種類型到另一種類型的明確轉換路徑。否則,他們可能會導致意想不到的結果和神祕的錯誤。

0

不幸的是,沒有這樣的事,作爲一個全球性的鑄造操作。出奇。但模板是你的朋友。

有時候你不想暴露鑄造界面看跌希望保持這種匿名的只是一個具體的實施。我通常會添加一個模板()方法,它也可以做中投類型檢查等,讓您處理您要實現鑄造(例如動態共享,文獻等)的方法的類。

事情是這樣的:

template< class EvtT >const EvtT& as() const throw(std::exception) 
    { 
     const EvtT* userData = static_cast<const EvtT*>(m_UserData); 
     ASSERT(userData, "Fatal error! No platform specific user data in input event!"); 
     return *userData; 
    } 

m_UserData是隻有實現知道匿名類型。雖然這是嚴格的非類型轉換(我在這裏不使用類型轉換),但這可以由dynamic_cast和適當的轉換異常來替代。

的執行簡單地做到這一點:

unsigned char GetRawKey(const InputEvent& ie) 
    { 
     const UserEvent& ue = ie.as<const UserEvent>(); 
     ...