Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ same function parameters with different return type

I need to find some way to mock an overload of a function return type in C++.

I know that there isn't a way to do that directly, but I'm hoping there's some out-of-the-box way around it. We're creating an API for users to work under, and they'll be passing in a data string that retrieves a value based on the string information. Those values are different types. In essence, we would like to let them do:

int = RetrieveValue(dataString1);
double = RetrieveValue(dataString2);
// Obviously, since they don't know the type, they wouldn't use int =.... It would be:
AnotherFunction(RetrieveValue(dataString1)); // param of type int
AnotherFunction(RetrieveValue(dataString2)); // param of type double

But that doesn't work in C++ (obviously). Right now, we're having it set up so that they call:

int = RetrieveValueInt(dataString1);
double = RetrieveValueDouble(dataString2);

However, we don't want them to need to know what the type of their data string is.

Unfortunately, we're not allowed to use external libraries, so no using Boost.

Are there any ways we can get around this?

Just to clarify, I understand that C++ can't natively do it. But there must be some way to get around it. For example, I thought about doing RetrieveValue(dataString1, GetType(dataString1)). That doesn't really fix anything, because GetType also can only have one return type. But I need something like that.

I understand that this question has been asked before, but in a different sense. I can't use any of the obvious answers. I need something completely out-of-the-box for it to be useful to me, which was not the case with any of the answers in the other question asked.

like image 596
Josh Johnson Avatar asked Feb 12 '13 19:02

Josh Johnson


2 Answers

You've to start with this:

template<typename T>
T RetrieveValue(std::string key)
{
     //get value and convert into T and return it
}

To support this function, you've to work a bit more, in order to convert the value into the type T. One easy way to convert value could be this:

template<typename T>
T RetrieveValue(std::string key)
{
     //get value
      std::string value = get_value(key, etc);

      std::stringstream ss(value);
      T convertedValue;
      if ( ss >> convertedValue ) return convertedValue;
      else throw std::runtime_error("conversion failed");
}

Note that you still have to call this function as:

int x = RetrieveValue<int>(key);

You could avoid mentioning int twice, if you could do this instead:

Value RetrieveValue(std::string key)
{
     //get value
      std::string value = get_value(key, etc);
      return { value };
}

where Value is implemented as:

struct Value
{
    std::string _value;

    template<typename T>
    operator T() const   //implicitly convert into T
    {
       std::stringstream ss(_value);
       T convertedValue;
       if ( ss >> convertedValue ) return convertedValue;
       else throw std::runtime_error("conversion failed");
    }
}

Then you could write this:

int    x = RetrieveValue(key1);
double y = RetrieveValue(key2);

which is which you want, right?

like image 141
Nawaz Avatar answered Sep 25 '22 13:09

Nawaz


Whether it is an overload or a specialization, you'll need the information to be in the function signature. You could pass the variable in as an unused 2nd argument:

int RetrieveValue(const std::string& s, const int&) {
  return atoi(s.c_str());
}
double RetrieveValue(const std::string& s, const double&) {
  return atof(s.c_str());
}

int i = RetrieveValue(dataString1, i);
double d = RetrieveValue(dataString2, d);
like image 44
Robᵩ Avatar answered Sep 22 '22 13:09

Robᵩ