我需要两个系统来映射类型 - 源数据字段,可以是数字,字符或字符串,都存储为字符串对象;目标系统需要为每个数据字段的基础类型使用不同的数据类型,我需要动态地执行此映射。
所以基本上,对于每个数据字段,我都有实际的字段字符串's'和底层数据的类型'type',我试图根据'type'转换为'dest'类型。我一直在尝试使用模板和模板常量来破解可以做到这一点的东西,没有运气。
我目前的尝试如下,但由于返回类型冲突,因此无法编译:
template<class CLASSTYPE, int CLASSID>
CLASSTYPE returnDifferentTypes()
{
using namespace std;
if (CLASSID == 1) // 1 = "string"
return std::string("returned string");
if (CLASSID == 2) // 2 = int
return 123;
if (CLASSID == 3) // 3 = double
return 123.123;
}
所以我一直在打电话给
string mapped = returnDifferentTypes<string, 1>()
or
int mapped = returnDifferentTypes<int, 2>()
任何人都可以推荐更智能的清洁方式来做到这一点吗?理想情况下,我试图返回适当的返回类型,只有一个表示要映射到的类型的字符串。提前谢谢。
答案 0 :(得分:5)
对于您的情况,CLASSID
是冗余参数;省略它。
对于不同的数据类型,您只需专门化方法returnDifferentTypes
即可获得更清晰的方式。
template<class CLASSTYPE>
CLASSTYPE returnDifferentTypes(); // undefined
template<>
std::string returnDifferentTypes<std::string>() { // for 'std::string'
return std::string("returned string");
}
template<>
int returnDifferentTypes<int>() { // for 'int'
return 123;
}
template<>
double returnDifferentTypes<double>() { // for 'double'
return 123.123;
}
用法:
string mapped = returnDifferentTypes<string>();
int mapped = returnDifferentTypes<int>();
答案 1 :(得分:3)
如果您可以静态识别ID,模板专业化可能比if-s网络更好。
template<int id>
struct multireturn; // not defined
template<>
struct multireturn<1>
{
typedef std::string return_type;
return_type operator()() { return "string"; }
};
template<>
struct multireturn<2>
{
typedef int return_type;
return_type operator()() { return 12; }
};
template<>
struct multireturn<3>
{
typedef double return_type;
return_type operator()() { return 12.3; }
};
///call like this
astring = multireturn<1>()()
aint = multireturn<2>()()
adouble = multireturn<3>()()
同样,您可以使用函数重载:
enum ret_string_t { ret_string; }
enum ret_int_t { ret_int; }
enum ret_ouble_t { ret_double; }
std::string multireturn(ret_string_t) { return "string"; }
int multireturn(ret_int_t) { return 12; }
int multireturn(ret_double_t) { return 12.34; }
/// call as:
astring = multireturn(ret_string);
aint= multireturn(ret_intg);
adouble= multireturn(ret_double);
或者 - 不那么正统,但仍在工作 -
struct multireturn
{
operator std::string() { return "text"; }
operator int() { return 10; }
operator doble() { return 3.5; }
};
///call as:
astring = multireturn();
aint = multireturn();
adouble = multireturn();
当然,必须根据所有示例的要求调整const正确性。
答案 2 :(得分:1)
除非你使用某种Variant类而不是string
来存储所有内容,否则在代码中的某些时候你需要有一种在类型之间选择的分支形式。但是,转换函数本身并不适合它。转换函数只能返回一种类型。如果您尝试在其中分支,则需要返回三种类型。除非你使用Variant或其他一些丑陋的黑客(例如void*
),否则你永远不会让它工作。
这里不需要函数模板特化,假设您接受在某个区域之间区分类型的分支。一个简单的CvtTo
函数模板可以完成这项工作:
#include <sstream>
#include <string>
template<class T> T CvtTo(const std::string& s)
{
stringstream ss;
ss << s;
T ret;
ss >> ret;
return ret;
}
现在完全接受您对分支逻辑的需求,并在您要存储数据时调用CvtTo
:
// SOME DATABASE FUNCTION N STUFF
std::string value = ...; // VALUE TO BE CONVERTED & STORED
enum FieldType {String, Int, Float};
FieldType field_type = ...;
switch( field_type )
{
case String :
store_a_string(CvtTo<std::string>(value)); // note this is not strictly necesarry for String
break;
case Int :
store_an_int(CvtTo<int>(value));
break;
case Float :
store_a_float(CvtTo<float>(value));
break;
}
// FURTHER MAGIC...
答案 3 :(得分:0)
如果您真的想要一个可以返回多种类型的函数,那么您正在寻找boost::variant
或boost::any
。
但是,请至少花点时间考虑一下为什么要这种行为,以及是否存在可能无需从同一函数返回多个不同类型的替代方法。
答案 4 :(得分:0)
如果要将数值或其他“iostream可序列化”类型转换为字符串,可以使用boost::lexical_cast
。