2008-10-16 68 views
3

一種隨機問題...任何只能用類操作符投射的方法?

我在尋找的是一種方法來表達一個強制轉換操作,該轉換操作使用我正在強制轉換的類實例的已定義操作符,並生成編譯時錯誤如果該類型沒有定義的演員操作符。因此,例如,我正在尋找的是這樣的:

template< typename RESULT_TYPE, typename INPUT_TYPE > 
RESULT_TYPE operator_cast(const INPUT_TYPE& tValue) 
{ 
    return tValue.operator RESULT_TYPE(); 
} 

// Should work... 
CString sString; 
LPCTSTR pcszString = operator_cast<LPCTSTR>(sString); 

// Should fail... 
int iValue = 42; 
DWORD dwValue = operator_cast<DWORD>(iValue); 

有趣的邊注:上面的代碼崩潰的VS2005 C++編譯器,以及不正確的VS2008 C++編譯器,由於編譯什麼我猜測是一個編譯器錯誤,但希望能夠證明這個想法。

任何人知道的任何方式來達到這種效果?

編輯:更多的理由,解釋爲什麼你會用這個。假設你有一個封裝類,它應該封裝或抽象一個類型,並且將它轉換爲封裝類型。你可以使用static_cast <>,但是當你想讓它失敗的時候它可能會工作(例如:編譯器選擇一個允許轉換爲你要求的類型的運算符,當你想要失敗時,因爲該運算符不存在)。

誠然這是一個罕見的情況,但是這很煩人,我不能表達正是我想要的編譯器中封裝的功能做......因此,這裏的問題。

回答

3

代碼您發佈與Cameau compiler作品(通常是一個很好的跡象,這是有效的C++)。

正如你所知,一個有效的演員陣容不超過一個用戶定義的陣容,所以我想到的一個可能的解決方案是通過在演員模板中定義一個新類型添加另一個用戶定義的演員陣容,並且有一個static assert沒有演員陣容可從新型的結果類型(使用boost is_convertible),然而這並不轉換運算符和鑄造的構造(構造函數使用一個參數)之間進行區分並且附加alows鑄件要發生(例如void*bool)。我不確定區分演員和演員是否是正確要做的事情,但這就是問題所在。

幾天後思索這個在打我,你可以簡單地採取強制轉換運算符的地址。這說起來容易做起來難,因爲C++的成員語法毛茸茸的指針(花了我的時間比預期的要長)。我不知道這是否適用於VS2008,我只在Cameau上檢查過它。

template< typename Res, typename T> 
Res operator_cast(const T& t) 
{ 
    typedef Res (T::*cast_op_t)() const; 
    cast_op_t cast_op = &T::operator Res; 
    return (t.*cast_op)(); 
} 

編輯:我有機會來測試它在VS2005和VS2008。我的發現不同於原始的海報。

  • 在VS2008上的原始版本似乎工作正常(如我的)。
  • 在VS2005上,原始版本在提供編譯錯誤後,從內置類型(例如,將int轉換爲int)拋出時纔會崩潰,編譯錯誤似乎並不那麼糟糕,我和我的版本似乎在所有情況下都能正常工作。
1

使用標記explicit一個轉換構造函數是你將如何阻止編譯器允許隱式轉換類型從初始化你的包裝類。

+0

是的,但是如果轉換爲內置的內部類型,我無法添加顯式構造函數或修改轉換行爲,那麼如何轉換? – Nick 2008-10-16 20:21:06

+0

你的意思是你想改變兩種內在類型之間的默認轉換行爲? – 2008-10-16 20:38:22

+0

不,我從包裝類轉換爲內在類型,所以我不能告訴編譯器我希望內在類型只能被明確地構造(並且在一般意義上也是不好的)。 – Nick 2008-10-16 21:54:48

0

聽起來像是你想模板特殊化,這樣的事情會做:

/* general template */ 
template<typename T1, typename T2> T1 operator_cast(const T2 &x); 

/* do this for each valid cast */ 
template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; } 

編輯:正如在另一篇文章中所指出的,你可以把一些在普通版本給你,如果一個更有用的錯誤信息不受支持的轉換被執行。

1

由於與模板相關的編譯器錯誤消息通常是一個解開的完全痛苦,如果您不介意指定每個轉換,您可以通過提供默認模板定義讓編譯器在失敗案例中發出更具啓發性的消息。這使用了一個事實,即編譯器只會嘗試在實際調用的模板中編譯代碼。

#include <string> 

// Class to trigger compiler warning 
class NO_OPERATOR_CONVERSION_AVAILABLE 
{ 
private: 
    NO_OPERATOR_CONVERSION_AVAILABLE(){}; 
}; 

// Default template definition to cause compiler error 
template<typename T1, typename T2> T1 operator_cast(const T2&) 
{ 
    NO_OPERATOR_CONVERSION_AVAILABLE a; 
    return T1(); 
} 

// Template specialisation 
template<> std::string operator_cast(const std::string &x) 
{ 
    return x; 
} 
相關問題