Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return both string and integer from a template function in C++

I am trying to write a generic function, using template, that is able to return bool, integer or char* or string.

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*
    }
}

and I would like to be able to call it like:

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

as an alternative for the char*, a string would be also fine:

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

I get errors like: "cannot convert from 'bool' to 'char*'. I understand the problem, the compiler is not able to detect that the code execution branch depends on the type I give. I just can't find a solution for that. Could anyone help me? Thanks.

like image 953
istik Avatar asked Apr 07 '26 15:04

istik


2 Answers

Since C++17 you can use constexpr if; whose condition part will be evaluated at the compile time, and if the result is true then the statement-false part (otherwise the statement-true part) will be discarded. (Thus won't cause the error.) e.g.

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

like image 177
songyuanyao Avatar answered Apr 09 '26 06:04

songyuanyao


For older versions of C++, you can solve this by forwarding to one of the overloaded functions that return result through argument passed by reference:

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);

Or you can use std::enable_if (since C++11):

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

But first solution, IMO, is more readable. You can make overloaded functions private, if you don't want to expose them.

like image 42
kjam Avatar answered Apr 09 '26 06:04

kjam