2013-05-11 111 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,它可以封装不同的类型。或者根据您的特定需求实施定制的变体解决方案。