静态声明源代码在C ++中不会改变

时间:2017-09-18 15:59:27

标签: c++ cross-platform backwards-compatibility static-assert

说我有一个不能改变的方法。如果这样的方法发生变化,C ++中是否有一种方法可以创建编译时错误(如果编译时间不可能,则为运行时)?

这种方法有很多用途(考虑到你不希望新手同事改变的棘手的线程或安全问题)。我的特定用例是保持向后兼容性,其中一些旧方法(如持久数据反序列化器)不得更改。

我想象的是以下内容:

static_assert(chechsumOfBelowFunction() != 0x123,
  "You changed the method! We can't do this because...")
std::string getRelaseDateForVersion3()
{
    // This should never change because "Version 3" was
    // only released once!
    return "2014-Jan-01";
}

其中checksumOfBelowFunction()在编译时计算函数的校验和或其他唯一表示(最好是跨平台),0x123是函数必须保留的已知参考校验和。请注意,我对伪代码采取了相当多的自由,但我希望我能传达我想要做的事情。

1 个答案:

答案 0 :(得分:1)

  

说我有一个不能改变的方法。如果这样的方法发生变化,C ++中是否有一种方法可以创建编译时错误(如果编译时间不可能,则为运行时)?

没有,没有办法(特别是如果你关心行为,而不是源代码)。请记住,两个函数的行为相等是一个不可判定的问题(相当于Halting Problem)。换句话说,equivalence of lambda terms(即两个C ++程序或子程序或函数)不可判定

您的要求(“不应更改”的功能或方法)定义错误。如果C ++源文件只是重新缩进怎么办?或者某些评论中的拼写错误会被纠正?或者一些局部变量的名称只是改变了?或者出于可读性原因,for循环被替换为一些等效的while?或者用更有效的二分法替代一些线性扫描;等....!

也许您可以将该函数放在自己的源文件中,计算一些加密哈希值,并将其放入构建过程中(例如Makefile make)。

您可以花费数月的时间研究更奇特的方法(例如,定制您的GCC编译器,可能在GCC MELT或某些GCC plugin中有一些扩展名),以便在g++编译器中进行计算你函数的GIMPLE AST的哈希应该保持不变,等等......)。我不确定这是值得的。

你可以有一些时间戳机器。

在我的许多Makefile中,我生成了一个__timestamp.c文件,例如像:

__timestamp.c: Makefile
    @(date +'const char bismon_timestamp[]="%c";'; \ 
     date +'%n const unsigned long bismon_timelong=%sL;' > __timestamp.tmp)
    @(echo -n 'const char bismon_lastgitcommit[]="' ; \
       git log --format=oneline --abbrev=12 --abbrev-commit -q  \
         | head -1 | tr -d '\n\r\f\"\\\\' ; \
       echo '";') >> __timestamp.tmp
    @(echo -n 'const char bismon_lastgittag[]="'; \
          (git describe --abbrev=0 --all || echo '*notag*') \
          | tr -d '\n\r\f\"\\\\'; echo '";') >> __timestamp.tmp
    @(echo -n 'const char bismon_checksum[]="'; cat bismon.h \
      $(BM_HEADERS) $(CSOURCES) | $(MD5SUM) \
     | cut -d' ' -f1 | tr -d '\n\r\f\"\\' ; echo '";') >> __timestamp.tmp
    @(echo -n 'const char bismon_directory[]="'; \
       /bin/pwd | tr -d '\n\\"' ; echo '";') >> __timestamp.tmp
    @(echo -n 'const char bismon_makefile[]="'; \
      echo -n  $(realpath $(lastword $(MAKEFILE_LIST))); \
      echo '";') >> __timestamp.tmp
    @mv __timestamp.tmp __timestamp.c

然后我在可执行文件中链接__timestamp.o;您也可以同样配置build automation工具。

  

我有一个不能改变的方法。

请注意,这是社交要求(与代码审核相关),而非软件要求。代码确实发生了变化(您希望technical debt避免code refactoring)。你的团队应该明智地使用一些好的version control software(例如git),你必须以某种方式信任你的同事(一个有恶意的,有能力的开发人员总能做坏事)。

(看起来像XY problem;也许你正在寻求一个纯粹的技术解决社会问题的方法)

  

我的特定用例是保持向后兼容性,其中一些旧方法(如持久数据反序列化器)不得更改。

通常的方法是在持久化数据中记录使用格式的版本(或签名)。如需灵感,请查看ELF或仅查看XML版本声明(XMLDecl)。

(关于dynamic software updating的论文可能会让你感兴趣)