我面临的情况是,我必须生成将从 JNI 使用的 C++ 代码。我已经与 java 对等体一起定义了传递数据的正确结构。然而,我被要求使用一个遗留的、老套的和 super 丑陋的结构,而不是设计的干净的结构。所以我有类似的东西:
struct NiceStructure{
int a;
int b;
bool c;
};
struct LegacyStructure{
string a;
double b;
bool c;
int old_dont_use;
string type;
int I_dont_remember_what_this_is_but_dont_touch_it;
bool clip;
};
NiceStructure
非常适合我想要执行的操作,并且 LegacyStructure
可以被黑客攻击(就像传统上那样)来完成我想做的事情。
问题是:我可以编写一个可以处理这两种结构的类型无关函数吗?
一个示例函数是:
vector<NiceStructure> do_something(vector<NiceStructure> array_of_values){
vector<NiceStructure> res;
for (int i=0; i< array_of_values.size(); i++){
if (array_of_values[i].a + array_of_values[i].b > 10 && array_of_values[i].c)
res.push_back(array_of_values[i])
}
return res;
}
我应该能够通过 LegacyStructure
更改类型 NiceStructure
并以某种方式使用它们中的任何一个。
最佳答案
首先,我会尽量避免编写适用于这两种数据类型的代码。相反,将转换器写入旧格式并隔离 LegacyStructure
尽早输入。
例如:
// Updates the LegacyStructure in place.
// This is our quarantine point.
void updateLegacy(LegacyStructure & s) {
NiceStructure n = fromLegacy(s);
updateNice(n);
syncLegacy(s, n);
}
// The brains is here, and its free from Legacy cruft
void updateNice(NiceStructure &n) { ... }
// We need a way to get back all the changed fields from
// a NiceStructure back into a LegacyStrcuture
void syncLegacy(LegacyStructure &s, const NiceStructure & n);
// And a way to get our initial NiceStructure
NiceStructure fromLegacy(const LegacyStructure & s);
如果最终需要避免数据拷贝(例如您正在处理 vector <LegacyStructure>
),那么有几个选项。我认为其中最巧妙的是实际使用模板,但要通过
一种特征类型方法,将每个字段作为通用类型进行访问。
// Base trait type -
// Trying to use this on any type we haven't specialised on
// will cause an error
template<typename T>
struct StructureTraits {};
// Specialisation of traits type for LegacyStructure
template<>
struct StructureTraits<LegacyStructure> {
static int getA(const LegacyStructure &s) { return int_from_string(s.a); }
static void setA(LegacyStructrue &s, int a) { s.a = string_from_int(s); }
...
};
// Specialisation of traits type for NiceStructure
template<>
struct StructureTraits<NiceStructure> {
static int getA(const NiceStructure &s) { return s.a; }
static void setA(LegacyStructure &s, int a) { s.a. = a; }
};
//TODO: Need some template hackery to provide const versions etc.
// This version will work for both types.
template<typename T>
void updateStructureList( std::vector<T> & structures ) {
for( auto & x : structures ) {
StructureTraits<T>::setA(x, StructureTraits<T>::getA(x) + 1 );
}
}
替代方法包括向两个类添加公共(public)基类型或为两个类创建带有简单包装器的接口(interface)。
关于c++ - 允许无缝使用两种变量类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44127176/