[英]How to get around inability to overload on return type in C++
我有可以創建許多不同模板類型的函數; 該問題的一個簡單示例是:
EncodedMsg<?>* encode(const Msg& msg)
{
if(msg.qty < 100)
return new EncodedMsg<short>(...);
else if(msg.qty < 100000)
return new EncodedMsg<int>(...);
else
return new EncodedMsg<long>(...);
}
我的問題是:
誰能想到解決這個問題的方法?
您試圖以動態方式使用模板,而這是不可能的。 模板的類型必須在編譯時就已知道,因此您不能基於一系列條件進行區分。
要在運行時更改類型,您將需要類和繼承的多態性。
基本上,如果測試變量msg.qty
不是編譯時常量,那么這將是不可能的。 您必須了解,模板可用於實現靜態多態性,而OOP(繼承)可用於實現動態多態性。 換句話說,模板在編譯時解析,而虛擬函數調用在運行時解析。 您可以同時使用兩者,但不能將它們用於相同的目的(即它們是互補的編程范例,每個范例都有各自的應用程序上下文)。
如果你可以,不過,得到msg.qty
是類型的編譯時間常數Msg
(即Msg::qty
,作為一個enum
或static const
),那么你可以使用boost::enable_if
庫。 因此:
template <class Msg>
typename boost::enable_if<Msg::qty < 100, EncodedMsg<short> >::type*
encode(const Msg& msg) { return new EncodedMsd<short>(...); };
template <class Msg>
typename boost::enable_if<((Msg::qty >= 100) && (Msg::qty < 100000)), EncodedMsg<short> >::type*
encode(const Msg& msg) { return new EncodedMsd<int>(...); };
template <class Msg>
typename boost::enable_if<Msg::qty >= 100000, EncodedMsg<short> >::type*
encode(const Msg& msg) { return new EncodedMsd<long>(...); };
但是,對於特定的Msg類,可以確定要對EncodedMsg使用哪種模板實例化,那么將其定義為Msg類中的嵌套typedef並定義編碼函數要容易得多:
template <class Msg>
Msg::encoded_type* encode(const Msg& msg) { return new Msg::encoded_type(...); };
如果您有不可修改的消息類,也可以使用類型特征(例如message_trait或類似的東西)來定義嵌套的typedef。
但是,如果msg.qty只能是運行時值,則別無選擇,只能使用動態多態性(即,將指針返回到基類或接口)。 或者,您也可以使用boost::variant
。 在這種情況下,您可以執行以下操作:
boost::variant< EncodedMsg<short>,
EncodedMsg<int>,
EncodedMsg<long> >* encode(const Msg& msg)
{
typedef boost::variant< EncodedMsg<short>,
EncodedMsg<int>,
EncodedMsg<long> > result_type;
if(msg.qty < 100)
return new result_type( EncodedMsg<short>(...) );
else if(msg.qty < 100000)
return new result_type( EncodedMsg<int>(...) );
else
return new result_type( EncodedMsg<long>(...) );
};
上面有一些明顯的問題(例如,結果類型將與EncodedMsg的最大模板實例化一樣大,但您可以通過附加級別的間接尋址(將指針存儲到EncodedMsg對象)解決該問題。 如果可以找到,它不如多態替代方案那么好和有效。
1)您不能重載函數的返回類型,但是可以重載傳遞給該函數的類型並通過指針傳遞。 但是,我認為這不是您想要的,請參閱2)
2)基本上,必須使用另一種設計方法來解決該問題:通過在基類中使用虛擬接口,您的方法將返回正確的類,並且僅調用適當的虛函數。 您只要返回基類(EncodedMsgBase),就可以是EncodedMsg_what,只要它是從EncodedMsgBase派生的。 您可以根據需要從基類創建模板。
在更復雜的情況下,這歸結為“如何在c ++中創建工廠”問題。 人們通常通過傳遞實現“虛擬構造函數”的基類來解決此問題。
查看c ++常見問題解答以獲取更多信息:
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8
還要記住,通過使用靜態類型可以避免很多麻煩:)
這種方法不允許您在需要進一步使用的任何地方使用EncodedMessage
(因為我懷疑例如EncodedMessage<long>
和EncodedMessage<short>
都應該可以傳遞給在EncodedMessages
上運行的某些方法)。
盡管您所要求的可以通過技巧完成,但我還是建議您重新考慮您的體系結構。
您可以簡單地堅持使用EncodedMessage<long>
並將其類型定義為TheOnlyPossibleEncodedMessage
如果可以用於所有消息數量)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.