允许无缝使用两种变量类型

时间:2017-05-23 06:20:58

标签: c++ templates

我处在这种情况下,我必须生成将要从JNI使用的C ++代码。我已经与java peer一起定义了传递数据的正确结构。然而,我被要求使用遗留的,hacky和超丑的结构而不是设计的干净结构。所以我有类似的东西:

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;
}

我应该可以通过NiceStructure更改LegacyStructure类型,并以某种方式使用其中任何一种。

1 个答案:

答案 0 :(得分:5)

首先,我会尽量避免编写适用于这两种数据类型的代码。而是将转换器与Legacy格式进行编写,并尽早隔离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);

如果最终需要避免数据的副本(例如,您正在处理向量<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 );
  }
}

替代方法包括向两个类添加公共基类型或使用两个类的简单包装器创建接口。