2013-05-11 115 views
4

下面的代碼片段是一個遊戲,編譯器抱怨返回值,所以我想要一些關於如何以其他方式做這個技巧的反饋,讓一個函數根據放入的類型返回兩種不同的類型但沒有超載返回多種類型

template <typename T> 
T GetTimeDead(uint64 Guid) 
{ 
    bool stringOutput; 
    if(typeid(T) == typeid(float)) 
     stringOutput = false; 
    else 
     stringOutput = true; 

    bool found = false; 
    for(map<uint32, TrackInfo>::iterator itr = dieTracker.begin(); itr != dieTracker.end(); ++itr) 
    { 
     if(itr->second.GUID == Guid) 
     { 
      found = true; 
      break; 
     } 
    } 

    if(!found) 
     stringOutput ? return "never" : return sObjectMgr->FindCreature(Guid)->GetCreatureData()->spawntimesecs; 

    if(!stringOutput) 
     return dieTracker.find(Guid)->second.seconds; 
    float seconds = dieTracker.find(Guid)->second.seconds; 
    uint64 secs = seconds % 60; 
    uint64 minutes = seconds % 3600/60; 
    uint64 hours = seconds % 86400/3600; 
    uint64 days = seconds/86400; 
    ostringstream ss; 
    if(days) 
     days != 1 ? ss << days << " Days " : ss << days << " Day "; 
    if(hours) 
     hours != 1 ? ss << hours << " Hours" : ss << hours << " Hour"; 
    if(minutes) 
     minutes != 1 ? ss << minutes << " Minutes " : ss << minutes << " Minutes "; 
    if(secs || (!days && !hours && !minutes)) 
     secs != 1 ? ss << secs << " Seconds " : ss << secs << " Second "; 
    ss << "ago"; 
    return ss.str(); 
} 
+1

什麼是錯誤? – 2013-05-11 19:35:21

+0

錯誤C2059:語法錯誤:'return' – user2373581 2013-05-11 19:37:12

+0

它聽起來像編譯器是正確的:你正在嘗試做一件壞事。你可以添加一個解釋你準備完成什麼? – Elazar 2013-05-11 19:37:37

回答

5

如果要定義通用的行爲與一個模板,但覆蓋此行爲少數特定類型,您應該使用模板專業化

template<typename T> 
std::string GetTimeDead(uint64 Guid) 
{ /* code to implement your version that returns std::string */ 
} 

template<> 
float GetTimeDead<float>(uint64 Guid) 
{ /* code to implement your version that returns float */ 
} 

之所以此刻你的錯誤是你定義的返回類型爲T。但是,您的邏輯已設置,因此如果T的類型爲float,則函數會嘗試返回std::string。從std::stringT可能沒有隱含的轉換,因此是錯誤。

如果您不想重複使用通用代碼,您可以將其提取到上述兩個調用的單獨模板函數中。

+2

如果你確實需要一個模板,你的答案很好。對我來說,這似乎不是這種情況。 – Elazar 2013-05-11 19:59:16

+0

我同意Elazar。模板參數僅用於確定是否返回字符串或浮點數。但是,如果你仍然因爲某種原因需要一個模板...你的剪輯是錯誤的。 – cwin 2013-05-11 20:05:28

+0

@ChriZzZ謝謝,我接受了編輯。 – user2093113 2013-05-11 20:14:53

0

關於錯誤error C2059: syntax error : 'return',這是解決這個問題具體錯誤的方式:

return stringOutput ? "never" : sObjectMgr->FindCreature(Guid)->GetCreatureData()->spawntimesecs; 

?:運算符是一個expressio n,並且運算符的每個參數都應該是一個表達式。 return陳述。不是一個表達。

作爲一個表達式,?:具有完全單一的類型。但是"never"spawntimesecs是不相關的類型。編譯器無法處理。這兩個值不屬於相同的?:表達式。

您可以使用聯合,但不推薦。

一個更好的解決方案將無法使用模板可言,因爲你不處於任何多方式使用類型參數:

float GetTimeDeadFloat(uint64 Guid) 
{ 
    return find(Guid) 
      ? dieTracker.find(Guid)->second.seconds 
      : sObjectMgr->FindCreature(Guid)->GetCreatureData()->spawntimesecs; 
} 

string GetTimeDeadString(uint64 Guid) 
{ 
    return find(Guid) 
      ? timeToString(dieTracker.find(Guid)->second.seconds) 
      : "never"; 
} 


bool find(uint64 Guid) { 
    for(map<uint32, TrackInfo>::iterator itr = dieTracker.begin(); itr != dieTracker.end(); ++itr) { 
     if(itr->second.GUID == Guid) 
      return true; 
    } 
    return false; 
} 

string timeToString(float seconds) { 
    string res = timeToString(seconds % 3600/60, "Minutes"); 
    res += timeToString(seconds % 86400/3600, "Hour"); 
    res += timeToString(seconds/86400, "Day"); 
    if (secs || res.length() == 0) 
     res += numToString(seconds % 60, "Second"); 
    res += "ago"; 
    return res; 
} 


string numToString(uint64 num, string type) { 
    ostringstream ss; 
    if (num) 
     ss << num << " " << type << (num != 1) ? "s" : "" << " "; 
    return ss.str(); 
} 
+0

stringoutput只是一個布爾值來檢查是否存在一個麻煩輸入.. – user2373581 2013-05-11 19:41:26

+0

但它是*運行時*檢查。所以它不會影響編譯時間類型。 – Elazar 2013-05-11 19:45:10

1

C++是一種強大且靜態類型的編譯語言 - 您不能擁有返回不同類型的函數。您僅限於單一返回類型。也就是說,你可以使用Boost的variant或Qt的QVariant,它可以封裝不同的類型。或者根據您的特定需求實施定製的變體解決方案。