C ++具有不同返回类型的相同函数参数

时间:2013-02-12 19:24:10

标签: c++ function types overloading

我需要找到一些方法来模拟C ++中函数返回类型的重载。

我知道没有办法直接这样做,但我希望有一些开箱即用的方法。 我们正在为用户创建一个API,他们将传入一个数据字符串,该字符串根据字符串信息检索值。这些值是不同的类型。从本质上讲,我们希望让他们这样做:

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

但这在C ++中不起作用(显然)。 现在,我们已经设置好了,所以他们打电话:

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

但是,我们不希望他们需要知道他们的数据字符串的类型。

不幸的是,我们不允许使用外部库,所以不使用Boost。

我们有什么方法可以解决这个问题吗?

只是为了澄清,我理解C ++本身不能这样做。但必须有一些方法来解决它。例如,我考虑过做RetrieveValue(dataString1,GetType(dataString1))。这并没有真正解决任何问题,因为GetType也只能有一种返回类型。但我需要这样的东西。

据我所知,此问题之前曾有过问题,但从不同的角度来看。我不能使用任何明显的答案。我需要一些完全开箱即用的东西,因为它对我有用,而其他问题中的任何答案都不是这样。

10 个答案:

答案 0 :(得分:22)

你要从这开始:

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

要支持此功能,您需要多做一些工作,以便将值转换为T类型。转换价值的一种简单方法是:

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

请注意,您仍然必须将此功能称为:

int x = RetrieveValue<int>(key);

如果您可以这样做,可以避免两次提及int

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

其中Value实现为:

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

然后你可以这样写:

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

你想要的,对吗?

答案 1 :(得分:1)

如果您知道您的值永远不会是零或负值,只需返回一个包含int和double的结构,并将您不需要的值清零...

这是一种便宜又脏兮兮的方式......

struct MyStruct{
int myInt;
double myDouble;
};

MyStruct MyFunction(){
}

答案 2 :(得分:1)

唯一明智的方法是将返回值移动到参数。

 void retrieve_value(std::string s, double& p);
 void retrieve_value(std::string s, int& p);
 <...>

 double x;
 retrieve_value(data_string1, x);

 int y;
 retrieve_value(data_string2, y);

答案 3 :(得分:1)

无论是重载还是专业化,您都需要将信息放在函数签名中。您可以将变量作为未使用的第二个参数传递:

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

答案 4 :(得分:1)

如果数据字符串是编译时常量(如回答我的评论中所述),则可以使用一些模板魔术来完成工作。一个更简单的选择是根本不使用字符串,而是使用某些数据类型,这些数据类型允许您在参数上重载。

struct retrieve_int {} as_int;
struct retrieve_double {} as_double;

int RetrieveValue(retrieve_int) { return 3; }
double RetrieveValue(retrieve_double) { return 7.0; }

auto x = RetrieveValue(as_int);    // x is int
auto y = RetrieveValue(as_double); // y is double

答案 5 :(得分:0)

不幸的是没有办法重载函数返回类型看到这个答案 Overloading by return type

答案 6 :(得分:0)

int a=itoa(retrieveValue(dataString));
double a=ftoa(retrieveValue(dataString));

都返回一个字符串。

答案 7 :(得分:0)

作为模板解决方案的替代方法,您可以让函数返回引用或指向类的指针,然后创建该类的子类以包含您要返回的不同数据类型。然后RetrieveValue将返回对相应子类的引用。

然后,用户将返回的对象传递给其他函数,而不知道它属于哪个子类。

这种情况下的问题将成为内存管理之一 - 选择哪个函数分配返回的对象以及哪个函数删除它,以及何时以这种方式避免内存泄漏。

答案 8 :(得分:0)

答案很简单,只需声明函数返回void *类型,然后在定义中返回对不同类型变量的引用。例如在标头(.h)中声明

void* RetrieveValue(string dataString1);

然后在定义(.cpp)中编写

void* RetrieveValue(string dataString1)
{
    if(dataString1.size()>4)
    {
        double value1=(double)dataString1.size();
        return &value1;
    }
    else
    {
        string value2=dataString1+"some string";
        return &value2;
    }
}

答案 9 :(得分:-2)

既然你使用了一个并不是你真正想要的例子,你就把所有人都抛弃了。

您真正拥有的设置(使用此函数的返回值调用其返回类型不可知的函数)将无效,因为函数调用在编译时已解析。

然后,您将被限制为运行时解决方案。我推荐访客模式,您必须大幅改变您的设计以允许此更改。我能看到的其他方式并非如此。