我需要找到一些方法来模拟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也只能有一种返回类型。但我需要这样的东西。
据我所知,此问题之前曾有过问题,但从不同的角度来看。我不能使用任何明显的答案。我需要一些完全开箱即用的东西,因为它对我有用,而其他问题中的任何答案都不是这样。
答案 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)
既然你使用了一个并不是你真正想要的例子,你就把所有人都抛弃了。
您真正拥有的设置(使用此函数的返回值调用其返回类型不可知的函数)将无效,因为函数调用在编译时已解析。
然后,您将被限制为运行时解决方案。我推荐访客模式,您必须大幅改变您的设计以允许此更改。我能看到的其他方式并非如此。