2017-07-07 106 views
2

我想寫一個通用函數,使用模板,能夠返回布爾,整數或char *或字符串。從C++中的模板函數返回字符串和整數

template<typename entryType> 
entryType getEntry(xml_node node, const char* entryKey) 
{ 
    ... 

    if (is_same<entryType, bool>::value) { 
     return boolvalue; //returning a boolean 
    } 
    else if(is_same<entryType, int>::value) { 
     return a; //this is an integer 
    } 
    else if (is_same<entryType, char*>::value) { 
     return result; //this is a char* 
    } 
} 

,我希望能夠調用它像:

bool bPublisher = getEntry<bool>(node, "Publisher"); 
int QoS = getEntry<int>(node, "QualityOfService"); 
char* sBrokerUrl = getEntry<char*>(node, "BrokerUrl"); 

作爲字符*替代,一個字符串也將是罰款:

string sBrokerUrl = getEntry<string>(node, "BrokerUrl"); 

我得到錯誤,如:「不能從'bool'轉換爲'char *'我理解這個問題,編譯器無法檢測到代碼執行分支取決於我給的類型,我只是找不到解決方案任何人都可以幫助我嗎? NKS。

+0

那麼,你不能用普通的'if'語句來做到這一點。 –

+1

如果語句 –

+1

需要專門化模板,則不能依賴運行時的返回類型。畢竟,一旦編譯完成,tempalte就成爲一個返回類型明確的普通函數 – user463035818

回答

0

如果C++ 17不提供給你,模板特可能會做你想要什麼:

template<typename entryType> 
entryType getEntry(xml_node node, const char* entryKey) {} 

template<> 
bool getEntry<bool>(xml_node node, const char* entryKey) { 
    return true; 
} 

template<> 
int getEntry<int>(xml_node node, const char* entryKey) { 
    return 1; 
} 

你可以把任何共享代碼在從每個專業調用的幫助函數中:

void shared_code(xml_node node, const char* entryKey) { 
    // ... 
} 

template<> 
bool getEntry<bool>(xml_node node, const char* entryKey) { 
    shared_code(node, entryKey); 
    return true; 
} 

template<> 
int getEntry<int>(xml_node node, const char* entryKey) { 
    shared_code(node, entryKey); 
    return 1; 
} 
3

既然C++ 17可以使用constexpr if;其條件部分將在編譯時進行評估,如果結果是true則聲明false部分(否則聲明真實部分)將被丟棄。 (因此不會導致錯誤。)例如

if constexpr (is_same<entryType, bool>::value) { 
    return boolvalue; //returning a boolean 
} 
else if constexpr (is_same<entryType, int>::value) { 
    return a; //this is an integer 
} 
else if constexpr (is_same<entryType, char*>::value) { 
    return result; //this is a char* 
} 

LIVE

+1

我正要發佈這個:| – P0W

+2

@ P0W全部關於FGITW –

+1

C++ 17解決方案在今後10年的現實生活中幾乎沒有用處 –

2

對於舊版本的C++的,您可以通過轉發來的重載函數返回通過引用傳遞參數導致一個解決這個問題:

template<typename entryType> 
entryType getEntry(xml_node node, const char* entryKey) 
{ 
    entryType result = entryType(); 
    this->getEntry(node, entryKey, result); 
    return result; 
} 

void getEntry(xml_node node, const char* entryKey, bool& result); 
void getEntry(xml_node node, const char* entryKey, int& result); 
void getEntry(xml_node node, const char* entryKey, char const *& result); 

或者你可以使用std::enable_if(因爲C++ 11):

template<typename entryType> 
typename std::enable_if<std::is_same<entryType, bool>::value, entryType>::type 
    getEntry(xml_node node, const char* entryKey) { 
    ... 
} 

但首先IMO的解決方案更具可讀性。如果你不想公開它們,你可以使重載函數保密。

1

像@ tobi303在評論中說,你應該專注於模板。 沒有必要花哨的SFINAE或其他技巧。

#include <iostream> 
#include <type_traits> 

using namespace std; 

template<typename entryType> 
entryType getEntry(const char* entryKey); 

template <> 
int getEntry<int>(const char* entryKey) 
{ 
    return 1; 
} 
template <> 
bool getEntry<bool>(const char* entryKey) 
{ 
    return false; 
} 
template <> 
string getEntry<string>(const char* entryKey) 
{ 
    return "asd"; 
} 

int main() { 
    bool bPublisher = getEntry<bool>("Publisher"); 
    int QoS = getEntry<int>("QualityOfService"); 
    string sBrokerUrl = getEntry<string>("BrokerUrl"); 

    cout << bPublisher << '\n' << QoS << '\n'<< sBrokerUrl << '\n'; 
} 

DEMO:https://wandbox.org/permlink/kyLuPyblb4zBi9fE

0

我想我會傾向於利用的std::tuple本已出色的功能性。

將標記值和標記值組合在一起,並且可以用最少的努力爲這種事物生成富有表現力的,類型安全的代碼。

#include <iostream> 
#include <tuple> 


template<class Tag, class Type> 
struct xmlvalue : Type 
{ 
    using Type::Type; 
}; 

template<class Tag> struct xmlvalue<Tag, bool> 
{ 
    xmlvalue(bool v) : value_(v) {} 

    operator bool&() { return value_; } 
    operator bool const&() const { return value_; } 

private: 
    bool value_; 
}; 

template<class Tag> struct xmlvalue<Tag, int> 
{ 
    xmlvalue(int v) : value_(v) {} 

    operator int&() { return value_; } 
    operator int const&() const { return value_; } 

private: 
    int value_; 
}; 

struct is_publisher_tag {}; 
struct qos_tag {}; 
struct broker_url_tag {}; 

using is_publisher = xmlvalue<is_publisher_tag, bool>; 
using qos = xmlvalue<qos_tag, int>; 
using broker_url = xmlvalue<broker_url_tag, std::string>; 


struct quote : std::tuple<is_publisher , qos, broker_url > 
{ 
    using std::tuple<is_publisher , qos, broker_url >::tuple; 
}; 

int main() { 

    auto q1 = quote(true, 100, "http:://foo.com"); 
    auto q2 = quote(false, 50, "http:://bar.com"); 

    std::cout << std::get<broker_url>(q1) << ", " << std::get<qos>(q1) << ", " << std::get<is_publisher>(q1) << std::endl; 
    std::cout << std::get<broker_url>(q2) << ", " << std::get<qos>(q2) << ", " << std::get<is_publisher>(q2) << std::endl; 

    return 0; 
} 

預期輸出:

http:://foo.com, 100, 1 
http:://bar.com, 50, 0