我想知道是否可以根据分配给它的变量类型来更改函数的返回类型。这是我的意思的一个简单例子。
我想创建一个从字符串中解析int,bool或float变量的函数。例如......
Int value = parse("37");
Float value = parse("3.14");
Bool value = parse("true");
我理解如果我将此函数设为模板,则必须从参数列表中确定变量类型,该列表始终是一个字符串。用c ++还有其他方法吗?
答案 0 :(得分:31)
这可以通过转换功能
完成struct proxy {
string str;
proxy(string const &str):str(str) { }
template<typename T> operator T() {
return boost::lexical_cast<T>(str);
}
};
proxy parse(string const &str) { return proxy(str); }
现在你只需要做
float a = parse("3.1");
它应该运作良好。顺便说一句,您可以直接使用该类。我建议将其重命名为conversion_proxy
,以指出它只是发生转化的代理,但它本身不会进行转换
struct conversion_proxy {
string str;
conversion_proxy(string const &str):str(str) { }
template<typename T> operator T() {
return boost::lexical_cast<T>(str);
}
};
float a = conversion_proxy("3.1");
答案 1 :(得分:12)
我不知道你的问题是否知道这一点,但你确实可以用模板做到这一点。唯一的问题是,您必须在每次调用时指定要转换的类型,而不是依赖于推理(因为正如您所说的那样,参数类型将始终相同)。
template<typename T> T parse(const string& str) { /* do stuff for other types */ }
template<> int parse<int>(const string& str) { /* do stuff for ints */ }
template<> double parse<double>(const string& str) { /* do stuff for doubles */ }
template<> bool parse<bool>(const string& str) { /* do stuff for bools */ }
// etc.
然后调用
int value = parse<int>("37");
double value = parse<double>("3.14");
bool value = parse<bool>("true");
如果您已经知道这一点,请忽略这个答案,但是您的问题并不清楚您是否知道这是可能的。
当然,如果您正在做的事情并不是真正的通用(因此您必须专门针对您要解析的每种类型),那么编写模板无论如何都不是正确的。
顺便说一句,你可以通过这样的单一函数来做到这一点(假设解析是你真正想做的事情):
#include <sstream>
template<typename T> T parse(const string& str)
{
T t;
std::istringstream sstr(str);
sstr >> t;
return t;
}
这适用于任何默认构造的,可流提取的类型,其中包含所有内置函数。
答案 2 :(得分:5)
您可以将输出参数作为指针或引用传递。
像这样:
template<class T> void parse(const std::string &input, T& output);
然后是这样的代码:
double d; parse(input, d);
int i; parse(input, i);
应该有用。
但是,您的代码看起来非常适合std :: istringstream,它只是:
istringstream is(input);
input >> d;
如果你有一些复杂的格式,我有一个相当不错的技巧涉及使用自定义运算符创建自定义对象&gt;&gt;拉出数据。
然后它可能会像:
istringstring is(input);
input >> LineExtracter(x, y, d);
答案 3 :(得分:3)
我同意litb比我自己快一点。使用铸造操作员。
#include <iostream>
#include <string>
#include <sstream>
class Convertible
{
public:
int m_Integer;
bool m_Bool;
double m_Double;
Convertible() : m_Integer(0), m_Bool(false), m_Double(0.0) {};
operator int() const
{
return m_Integer;
}
operator bool() const
{
return m_Bool;
}
operator double() const
{
return m_Double;
}
};
Convertible parse(std::string data)
{
Convertible l_result;
std::istringstream converter(data);
converter >> l_result.m_Integer;
std::istringstream converter2(data);
converter2 >> l_result.m_Bool;
std::istringstream converter3(data);
converter3 >> l_result.m_Double;
return l_result;
}
void main()
{
int l_convertedInt = parse("2");
bool l_convertedBool = parse("true");
double l_convertedDouble = parse("3.14");
std::cout << "Converted '2' to " << l_convertedInt << std::endl;
std::cout << "Converted 'true' to " << l_convertedBool << std::endl;
std::cout << "Converted '3.14' to " << l_convertedDouble << std::endl;
}
答案 4 :(得分:0)
不幸的是,这是不可能的。在C ++中,不可能根据函数的返回值重载函数。你要么必须有3个函数,ParseInt,ParseFloat和ParseBool,要么使用函数模板。
答案 5 :(得分:0)
您可以返回void *,然后根据需要投射结果。
我建议不要这样做。 C ++是一种强类型语言。这样做的好处是编译器可以比动态类型语言更早地捕获错误。
答案 6 :(得分:0)
在C ++中不可能出现这种类型的行为。为了允许,必须能够在相同的范围内定义相同名称的函数,这些函数仅与返回类型不同。这在C ++中是不合法的。
C ++可以在重写的虚函数上执行一些返回类型特化,例如协变返回类型。但它不支持您正在寻找的东西。
答案 7 :(得分:0)
这是我对@Tyler McHenry's answer的改编,我的情况是parse()
的参数是一个字符串以外的类型。
请注意,我发现我必须引入模板专精,以避免类型转换警告(float
到int
)。
(另见live demo。)
#include <iostream>
struct MyUnion
{
public:
union {
bool bool_value;
int int_value;
float float_value;
};
};
template<typename T> T parse(const MyUnion& h)
{
T t;
if (typeid(T) == typeid(bool)) {
t = h.bool_value;
} else if (typeid(T) == typeid(int)) {
t = h.int_value;
} else if (typeid(T) == typeid(float)) {
// t = h.float_value; // see **Warning** below; use float specialization instead
}
return t;
}
// 'float' template specialization to avoid conversion warning.
template<> float parse(const MyUnion& h)
{
return h.float_value;
}
int main()
{
MyUnion mu1; mu1.bool_value = true;
MyUnion mu2; mu2.int_value = 42;
MyUnion mu3; mu3.float_value = 3.14159;
std::cout << "As bool: " << parse<bool>(mu1) << std::endl;
std::cout << "As int: " << parse<int>(mu2) << std::endl;
std::cout << "As float: " << parse<float>(mu3) << std::endl;
}
// **Warning**
// In function 'T parse(const Heterogeneous&) [with T = int]':
// Line 22: warning: converting to 'int' from 'const float'