static_assert C++ 与 C 中的用法

static_assert usage in C++ vs C

这是一个庞大项目的一部分,所以我 post 从一个 cc 文件中摘录(实际代码中只需要一个 static_assert,我只是试验了一下):

namespace large
{

static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");  // A

namespace fake_n
{
  static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");  // B
}

class fake_c
{
  static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");  // C
};

void fake_f()
{
  static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");  // D
}

}  // namespace large

gcc9 报如下错误(A、B、C、D 分别对应):

A,B : error: expected constructor, destructor, or type conversion before '(' token

C : error: expected identifier before 'sizeof'
  : error: expected ',' or '...' before 'sizeof'
  : error: ISO C++ forbids declaration of '_Static_assert' with no type [-fpermissive]

D : error: '_Static_assert' was not declared in this scope; did you mean 'static_assert'?

最后一个错误让我认为问题出在 以某种方式包含(通过一长串包含)。我找到它并删除了“#include ”,之后所有错误都消失了。

问题:

  1. 案例 A、B、C 中的错误是什么意思?
  2. 最重要的:一般情况下如何处理混合C和C++文件? 如果我无法删除(甚至找不到)相应的 怎么办?我如何告诉编译器使用 C++ 版本的 static_assert,而不是 C 宏?

谢谢!

  1. Most important: how to handle in general situation with mixing C and C++ files?

您可以 link 使用 C++ 编译器编译的 C++ 翻译单元和使用 C 编译器编译的 C 翻译单元。您可以使用语言的通用子集编写头文件。您可以在必要时使用宏来改变声明 - 最常见的是在包含在 C++ 中时将 C linkage 说明符添加到声明中。

How can I tell compiler to use C++ version of static_assert, not C macro?

使用符合标准的C++语言实现,没有问题。这是您在 GCC 9 中运行的示例程序:https://godbolt.org/z/hEsMT8W93

  1. 你的一个 header 中的某些东西似乎在做 #define static_assert _Static_assert,这在 C++ 中失败了,因为 _Static_assert 是一个(保留的)标识符,没有特殊的意义;特别是它不执行静态断言。我通过手动添加 #define static_assert _Static_assertan example 中得到相同的错误,如果我这样做 #define static_assert foobar.

    也会得到类似的错误

    当编译为 C 时,这个宏应该在 <assert.h> 中,但是正确编写的 <assert.h> 应该将它包装在 #ifndef __cplusplus 中,这样它就不适用于 C++ 源代码。所以我怀疑:

    • 你的系统 <assert.h> 坏了

    • 您的编译器对它正在编译的语言感到困惑(不太可能因为 namespace 等也将是语法错误)

    • 在你的 headers(或 command-line 编译选项)的纠结中还有一些东西很顽皮,导致 #undef __cplusplus 或类似的东西。如果您找到包含 <assert.h> 的地方,您可以尝试通过战略性插入

      来追踪问题
#ifndef __cplusplus
#error Aargh
#endif
  1. 通常你不需要做任何事情。正确编写的系统 headers 将通过适当的 #ifdefs 支持 C++,并在包含到 C++ 程序中时正常工作。

    如果您有来自某个 third-party 库的 header 仅以 C 语言编写且不支持 C++,那么您需要做一些工作来适应它(或抱怨它供应商)。这是一个超出此答案范围的项目。将所有内容包装在 extern "C" 中是一个开始,但只是一个开始。