如何最好地防止库(源)和应用程序(头)编译之间的(编译器)标志不匹配

How to best safeguard against mismatch of (compiler) flags between library (source) and application (header) compilations?

本文关键字:之间 编译 编译器 不匹配 标志 应用程序 何最好      更新时间:2023-10-16

在实现头文件中给定的某些接口时,如何最好地防止库实现的编译与头文件之间的危险不匹配?

详细信息:库接口由头文件(例如foo.h)提供,并由某些源文件(例如,foo.cc)实现。后者被编译以创建库,例如libfoo.so,而前者#include<>由一个应用程序执行,该应用程序与libfoo.so链接。

现在,假设在foo.h

// foo.h
namespace foo {
  class bar
  {
#ifdef SomeOption
    std::int32_t x[2];
#else
    std::int64_t x[2];
#endif
    bar const*ptr;
    /* ... */
  };
}

ptr的偏移量是8或16字节,这取决于SomeOption(并且sizeof(bar)也不同)。现在,如果使用与应用程序不同的SomeOption值编译库,那么显然会出现严重的问题(对于不知情的人来说很难调试)。

解决方案所以,我想出了以下想法

// foo.h
namespace foo {
  enum { hasSomeOption = 1 };
  int options_flags()
  {
    return 0
#ifdef SomeOption
    | hasSomeOption
#endif
    ;
  }
  class bar
  {
    /* ... as before */ 
    bar(some_args, int);
  public:
    bar(some_args) : bar(some_args, options_flags()) {} // what's option_flags()?
    /* ... */
  };
}

// foo.cc
namespace {
  const int src_flags = options_flags(); // flags used for compiling library source
}
namespace foo {
  bar::bar(some_args, int app_flags)
  {        
    assert(app_flags == src_flags);
    /* ... */
  }
}

具有CCD_ 11将捕获任何不一致的想法。然而,这不起作用:编译器似乎优化了我的想法,断言永远不会触发,即使SomeOption不同于库和应用程序编译。

问题对于这类问题,有推荐的最佳方法吗?

我希望有更好的方法,但您可以随时根据选项更改类或命名空间名称,这样,如果有人使用了错误的编译器选项,就找不到类。

更改名称空间的名称似乎更好——使用调试器时不会引起太多混乱。类似这样的东西:

#ifdef SomeOption
    #define foo foo_32bit
#else
    #define foo foo_64bit
#endif
namespace foo
{
 ....
}

我想它会起作用,但它确实很难看。

相关文章: