2017-10-11 35 views
0

我有一个类名为Eclipse与私人结构成员包含~30各种数据类型的字段。使用追踪返回类型的写入方法根据方法调用进行更改?

我有将从该结构返回的数据字段,根据传递作为参数的字段数目的方法。

由于结构体包含各种类型的数据,因此我选择使用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并返回结构的第一列(对应于第一个字段)。但我收到此编译错误:

no viable conversion from returned value of type 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to function return type 'decltype(toGet)' (aka 'int')`

我明白,如果我要调用此方法与int作为第一个参数,以及对应于田间返回std::string场数,就不会有的问题。但是,根据其他类别的检查,这种情况绝不会发生。

有什么办法,我可以强迫我的编译器,接受此代码,即使它可能不适用于某些情况下是正确的?

我知道我可以只重载方法,但我宁愿不具备基本相同目的的多种不同的方法,如果我能想出如何完成这个任务只有一个。

而且,如果我的任何信息的理解似乎不正确,请让我知道。我对C++非常陌生,所以我只是在学习这些功能。

+0

这完全不正确。如果第一个参数是一个“int”,那么decltype指定该函数根据定义返回一个“int”。句号。故事结局。从那时起你写的所有内容都是不相关的。实例化的模板函数必须返回一个“int”,否则ifs,ands或buts。 –

回答

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 
} 

但后来你遇到了,并不是所有的字段将转换为返回类型问题(当请求int等不能返回std::string场),所以你不能只是switchfieldNum,因为它是不在编译时进行评估。

你可能想使字段数是一个模板参数,因此恒定在编译时间,然后专注于它:

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>(); 

但是,没有按”或者(“不一致的扣除自动返回类型”错误)。