我有一个名为Eclipse
的类,其中包含一个包含~30个不同数据类型字段的私有结构成员。
我有一个方法,它将根据作为参数传入的字段编号从结构中返回一个数据字段。
看到struct包含各种类型的数据,我选择使用基于模板化参数的auto
关键字和尾随返回类型。我的方法标题如下。
template<typename TheType>
auto getColumnData(TheType toGet, int fieldNum) -> decltype(toGet) {
// switch statement to return fields based on fieldNum
}
如果我想要返回int
的列,请致电getColumnData(0, 1);
。第一个参数仅用于确定方法的返回类型,第二个参数确定要返回给方法调用者的字段编号。
理论上,这会导致getColumnData()
的返回类型为int
并返回结构的第一列(对应于第一个字段)。但是我收到了这个编译错误:
没有可行的转换,从'std :: string'类型的返回值(又名'basic_string&lt; char,char_traits&lt; char&gt;,allocator&lt; char&gt;&gt;')到函数返回类型'decltype(toGet)'(又名' INT')`
我理解,如果我使用int
作为第一个参数调用此方法,并且字段编号对应于返回std::string
的字段,则会出现问题。但是,基于其他类中的检查,这种情况永远不会发生。
有什么方法可以强制我的编译器接受这个代码,即使它在某些情况下可能不正确吗?
我知道我可以重载方法,但如果我能弄清楚如何只用一个完成任务,我宁愿没有多种不同的方法用于基本相同的目的。
另外,如果我对这些信息的理解不正确,请告诉我。我对C ++很新,所以我只是在学习这些功能。
答案 0 :(得分:0)
您无法在运行时动态更改方法的返回类型,就像您尝试的那样。您的第一个参数不是编译时已知的数据类型。它只是一个在运行时填充的整数,因此您根本不能根据它做出编译时决定。
一个简单的解决方案是使用std::variant
(C ++ 17或更高版本)或boost::variant
(C ++ 11及更高版本)作为返回类型:
using FieldType = std:::variant<int, std::string>;
FieldType getColumnData(int fieldNum) {
// switch statement to return fields based on fieldNum
}
int i = std::get<int>(getColumnData(1));
std::string s = std::get<std::string>(getColumnData(2));
否则,您必须将返回类型设为模板参数,而不是方法参数:
template<typename TheType>
TheType getColumnData(int fieldNum) {
// switch statement to return fields based on fieldNum
}
但是你遇到的问题是并非所有字段都可以转换为返回类型(请求std::string
时无法返回int
字段等),所以你可以'仅switch
上的fieldNum
,因为它不会在编译时进行评估。
您可能想让字段编号成为模板参数,因此它在编译时是常量,然后专门针对它:
template<const int FieldNum>
auto getColumnData() { return 0; };
template<> int getColumnData<1>() { return private_struct.Field1; }
template<> std::string getColumnData<2>() { return private_struct.Field2; }
// etc...
int i = getColumnData<1>();
std::string s = getColumnData<2>();
但是当我尝试在模板化的类方法(“非命名空间范围中的显式特化”)上执行此操作时,我会收到错误。
您可能想做类似的事情,并希望编译器优化掉未使用的分支:
template<const int FieldNum>
auto getColumnData() {
if (FieldNum == 1) return private_struct.Field1;
if (FieldNum == 2) return private_struct.Field2;
//etc...
return 0;
}
或
template<const int FieldNum>
auto getColumnData()
{
switch (FieldNum) {
case 1: return private_struct.Field1;
case 2: return private_struct.Field2;
// etc...
}
return 0;
};
int i = getColumnData<1>();
std::string s = getColumnData<2>();
但这也不起作用(“自动返回类型的错误扣除”错误)。