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

标签 c++ templates

我面临的情况是,我必须生成将从 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/

相关文章:

c++ - 添加根目录作为包含目录

c++ - FindFirstFile、FindNextFile API 是否不可靠?

c++ - 如何在 C++ 中比较两个泛型类型?

c++ - 在 C++ 模板参数中不使用 constexpr

c++ - 在 C++ 编译时计算和打印阶乘

C++ 无法专门化函数模板

c++ - 有人可以帮我做一个 while 循环,这样我就可以在每次计算后继续输入 cin 值吗?

c++ - 数组订阅 : returning Reference vs proxy class method

c++ - 使用 qFromBigEndian 编译错误

c++ - 如何在具有依赖元素类型的模板类构造函数中初始化 vector