我想知道是否可以根据分配给它的变量类型来更改函数的返回类型。这是我的意思的一个快速示例。
我想创建一个函数来解析字符串中的 int、bool 或 float 变量。例如...
Int value = parse("37");
Float value = parse("3.14");
Bool value = parse("true");
我知道如果我将此函数设为模板,则必须从始终为字符串的参数列表中确定变量类型。有没有其他方法可以用 c++ 做到这一点?
这可以通过转换函数来完成
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");
我无法从您的问题中判断您是否知道这一点,但您确实可以使用模板来做到这一点。唯一的问题是,您必须在每次调用中指定要转换的类型,而不是依赖推理(因为正如您所说,参数类型将始终相同)。
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");
如果您已经知道这一点,请忽略此答案,但从您的问题中不清楚您是否知道这是可能的。
当然,如果您正在做的事情不是真正通用的(因此您必须专门针对要解析的每种类型),那么编写模板无论如何都不是正确的事情。
顺便说一句,您可以使用这样的单个函数非常通用地完成它(假设 parse 是您真正想要做的):
#include <sstream>
template<typename T> T parse(const string& str)
{
T t;
std::istringstream sstr(str);
sstr >> t;
return t;
}
这适用于任何默认可构造、可流提取的类型,包括所有内置函数。
您可以将输出参数作为指针或引用传递。
像这样:
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;
如果你有一些复杂的格式,我很幸运的一个技巧是使用自定义操作符>>创建自定义对象来提取数据。
那么它可能是这样的:
istringstring is(input);
input >> LineExtracter(x, y, d);
我会同意比我快一点的 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;
}
不幸的是,这是不可能的。在 C++ 中,不可能根据函数的返回值重载函数。您要么必须拥有 3 个函数,ParseInt、ParseFloat 和 ParseBool,要么使用函数模板。
您可以返回 void* 然后根据需要转换结果。
我建议不要这样做。C++ 是一种强类型语言。这样做的好处是编译器可以比动态类型语言更早地捕获错误。
不,这种行为在 C++ 中是不可能的。为了允许,它必须能够在相同的范围内定义相同名称的函数,这些函数仅在返回类型上有所不同。这在 C++ 中是不合法的。
C++ 可以做一些返回类型的特殊化,例如覆盖虚函数的协变返回类型。但它不支持您要查找的内容。
这是我对@Tyler McHenry 的答案的改编,适用于我的情况,其中的参数parse()
是字符串以外的类型。
请注意,我发现我必须引入模板专业化以避免类型转换警告(float
to int
)。
(另见现场演示。)
#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'