【问题标题】:static_assert usage in C++ vs CC++ 与 C 中的 static_assert 用法
【发布时间】:2021-03-23 00:50:22
【问题描述】:

这是一个巨大项目的一部分,所以我从一个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 宏?

谢谢!

【问题讨论】:

  • 有问题的 C 版本在哪里?这都是纯 C++ 代码。如果您包含<assert.h>,您可能会遇到麻烦。
  • @tadman 我指的是 中的 C 宏 "static_assert",请参阅 en.cppreference.com/w/c/language/_Static_assert
  • 似乎在这里工作正常:godbolt.org/z/Ys5oqYG96。也许您的系统标头有问题?什么操作系统和版本?如果您仅#include <assert.h> 会失败,还是 MRE 需要其他东西?
  • Ubuntu 上的<assert.h>#define static_assert _Static_assert 包裹在#if !defined __cplusplus 中,所以没有问题。如果你的没有,那么它可能会损坏。
  • 无论如何,这也表明在您的#includes 之后的#undef static_assert 可能是一个简单的解决方法。

标签: c++ c static-assert


【解决方案1】:
  1. 您的某个标头中的某些内容似乎在执行#define static_assert _Static_assert,这在 C++ 中失败,因为_Static_assert 是一个没有特殊含义的(保留)标识符;特别是它不执行静态断言。通过手动添加#define static_assert _Static_assert,我会在an example 中遇到相同的错误,如果我添加#define static_assert foobar,则会遇到类似的错误。

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

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

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

    • 你纠结的标题(或命令行编译选项)中的其他东西很顽皮,导致#undef __cplusplus 或类似的东西。如果您找到了包含<assert.h> 的位置,您可以尝试通过策略性插入来追踪问题

#ifndef __cplusplus
#error Aargh
#endif
  1. 通常你不应该做任何事情。正确编写的系统头文件将通过适当的#ifdefs 支持 C++,并在包含到 C++ 程序中时正常工作。

    如果您有某个第三方库的标头,该标头仅用 C 编写且不支持 C++,那么您需要做一些工作来调整它(或向其供应商投诉)。这是一个超出此答案范围的项目。将所有内容包装在 extern "C" 中是一个开始,但只是一个开始。

【讨论】:

    【解决方案2】:
    1. 最重要的是:在一般情况下如何处理混合 C 和 C++ 文件?

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

    如何告诉编译器使用 C++ 版本的 static_assert,而不是 C 宏?

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多