在旧代码中创建基于类型的标识号,更改最少

Posted

技术标签:

【中文标题】在旧代码中创建基于类型的标识号,更改最少【英文标题】:Creating a type based identification number in old code with minimal changes 【发布时间】:2012-10-09 01:49:21 【问题描述】:

我正在维护一个非常古老(20 多年)且相当大(15 KLOC)的库,其中包含当前由整数标识的各种类型的对象。这提出了一个问题,即只给定整数,我不知道它应该识别哪种类型的对象。在编译时这样做会非常好。

我想出的解决方案是进行了最小的更改,即创建一个 ID 模板,然后为它为各种类型的对象 ID 创建 typedef。

我意识到我必须在模板中添加第三个参数,因为我认为两个完全不同的标识符可能具有相同的基础类型和范围。

我发现C++不考虑

typedef int X;
typedef int Y;

作为完全不同的类型。

这是解决方案吗:-

A) 合理(我知道它有效)

B) 是否有另一种简单的方法来做到这一点 - 管理层害怕高 LOC 变化

仅使用示例运算符简化解决方案。

#include <iostream>

// Horrible old definition of current code
class OldObjectA

   public:
      int ident_; // int identifier
      int uniq_;  // another int identifier unique to OldObjectA's only
;

class OldObjectB

   public:
      int ident_;
      int next_; // int of another OldObjectB ident_
      int uniq_; // another int identifier unique to OldObjectB's only
      int dq_;   // int of yet anothera OldObjectB ident_
      int com_;  // int of ident_ of a OldObjectA
      int ld_;   // int of ident_ of a OldObjectC
;

class OldObjectC

   public:
      int indent_;
      int next_; // int of another OldObjectC ident_
      int com_;  // int of ident_ of a OldObjectA
;

enum Type  TypeA, TypeAU, TypeB, TypeBU, TypeC ;

template<class T, T maxval, Type type>
class ID

   public:
      friend bool operator==(const ID<T, maxval, type> &lhs, const ID<T, maxval, type> &rhs)
      
         std::cout << __PRETTY_FUNCTION__ << std::endl;
         return true;
      
;

typedef ID<int, 42, TypeA>  ID_A;
typedef ID<int, 42, TypeAU> ID_UniqA;
typedef ID<int, 42, TypeB>  ID_B;
typedef ID<int, 42, TypeBU> ID_UniqB;
typedef ID<int, 100, TypeC> ID_C;

// What I was thinking of doing
class NewObjectA

   public:
      ID_A ident_; // int identifier
      ID_UniqA uniq_;  // another int identifer
;

class NewObjectB

   public:
      ID_B ident_;
      ID_B next_; // int of another OldObjectB ident_
      ID_UniqB uniq_; // another int
      ID_B dq_;   // int of yet anothera OldObjectB ident_
      ID_A com_;  // int of ident_ of a OldObjectA
      ID_C ld_;   // int of ident_ of a OldObjectC
;

class NewObjectC

   public:
      ID_C indent_;
      ID_C next_; // int of another OldObjectC ident_
      ID_A com_;  // int of ident_ of a OldObjectA
;

int main(int argc, char *argv[])

   std::cout << "================================================================================\n";
   ID_A a,a2;
   ID_UniqA au,au2;
   ID_B b,b2;
   ID_UniqB bu,bu2;
   ID_C c,c2;

   a==a2;
   au==au2;
   b==b2;
   bu==bu2;
   c==c2;

   // wanted and expected compile time fails
   // a=au;
   // a=b;
   // a=bu;
   // a=c;
   // au=b;
   // au=bu;
   // au=c;
   // b=bu;
   // b=c;

   std::cout << "================================================================================\n";


  return 0;

【问题讨论】:

【参考方案1】:

添加模板参数以区分其他相同类型的想法是合理的。这是一种有用的技术,每隔一段时间就会出现一次。最近,我在定义测量类型(即公里、升、秒等)时使用了类似的技术。

您可以对现有的内容进行至少一种简化。枚举不是必需的。您可以在 ID 定义中使用类型本身。

template<class T, T maxval, class tag>
struct ID 
;

template<class T, T maxval, class tag>
bool operator==(ID<T, maxval, tag> lhs, ID<T, maxval, tag> rhs)

    return true;


typedef ID<int, 42, class NewObjectA> ID_A;
typedef ID<int, 42, class NewObjectB> ID_B;

struct NewObjectA 
    ID_A id;
;

struct NewObjectB 
    ID_B id;
;

void f()

    ID_A id_a;
    ID_B id_b;

    id_a == id_a;
    id_b == id_b;
    //id_a == id_b; // won't compile as expected

这样做的好处是不会在一个地方创建程序中所有类型的全局列表。如果您需要根据继承层次结构允许的转换来处理 ID,使用类型本身也可能会使事情变得更容易。例如,ObjectC 是 ObjectA,因此 ID_C 可以转换为 ID_A。

我发现通过添加这种东西(我正在做的测量工作是相似的),增量方法通常是要走的路。每次您需要修改一段代码时,都会在本地引入一些改进,并在进行更多更改之前确认它们按预期工作。如果您认为您已经确定了一个错误并改变了程序行为,那么测试这些更改尤其重要。相比之下,试图一次全部改变一切往往会很痛苦。

【讨论】:

以上是关于在旧代码中创建基于类型的标识号,更改最少的主要内容,如果未能解决你的问题,请参考以下文章

Java在Interface中创建方法并更改参数类型

如何在 TypeScript 中创建自定义类型

如何像在 babelrc 中创建依赖别名一样在 typescript 中创建类型别名?

Python-变量类型

Python-变量类型

在云代码中创建ACL时出错:无效的权限类型