c++ - 如何在不同命名空间中使用双重声明的 extern "C"函数进行 clang 构建(如 msvc 和 gcc)

标签 c++ c clang++

我有这个项目,其中包含其他两个项目,它们为同一个 DLL 提供 header 。在一个 header 中,声明被放入命名空间中,而在另一个 header 中则不然。 这对于 GCC 和 MSVC 来说效果很好,但我无法说服 clang 编译它。 所以一个最小的例子是:

x.h:

#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__

namespace XX {
  struct Type {
    std::string name;
  };

  extern "C" int Func(Type);
}

包括.h:

#include <string>
#if defined __GNUC__
# pragma GCC system_header
#endif // __GNUC__

struct Type {
  std::string name;
};

extern "C" int Func(Type);

main.cpp

#include "incl.h"
#include "x.h"

int main()
{
  return 0;
}

G++ 发出警告,但已使用 # pragma GCC system_header 关闭。 那么,我怎样才能让 clang 在这样的环境中构建呢?

最佳答案

[dcl.link] At most one function with a particular name can have C language linkage. Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function. ...

因此,::FuncXX::Func 必须引用相同的函数。但是您的两个声明具有不同的参数列表 - 一个采用 ::Type 参数,而另一个采用 XX::Type 参数。因此,它们不能是相同的函数,因此违反了引用的规则,并且程序格式不正确。曾经

修复程序的几种方法:

  • 重命名 XX::Func::Func,使它们成为单独的函数。确保每个都有一个定义。
  • incl.h 中,包含 x.h 并将 ::Type 的定义替换为 using XX::Type 。因此每个 Type 都引用相同的类型,因此两个函数名称都引用相同的函数。确保只有一个定义。
  • x.h 中,包含 incl.h 并将 XX::Type 的定义替换为 using ::Type 。达到与上面相同的效果。

顺便说一句,后者是一些标准库实现如何实现 <cstdlib> 及其 friend 的。它们包含相应的 C 标准库 header (在 <stdlib.h> 的情况下为 <cstdlib> ),该 header 声明了全局命名空间(C 中唯一的“命名空间”)中的所有内容,然后它们使用 std 将所有标准函数和类型选择到 using ::whatever 命名空间中。


附注不要使用 #pragma GCC system_header(除非您正在编写系统 header )。它将抑制所有警告(由 #warning 指令生成的警告除外)。

关于c++ - 如何在不同命名空间中使用双重声明的 extern "C"函数进行 clang 构建(如 msvc 和 gcc),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55867172/

相关文章:

c++ - 如何将 const char* 转换为 const WCHAR*

c++字符串文字并置连接

c - 为什么内部 Lua 字符串会这样存储?

c++ - 编译模板时出现 clang 错误

C++ 模板特化和继承

warnings - 如何抑制 clang++ 中的警告?

c++ - 在打开 vsync 的情况下执行 glTexImage2D 时出现奇怪的延迟

c++ - 使用数组和 for 循环但不使用字符串或任何类

java - 如何使用 C/java 检测 Activity 应用程序?

c - 在 C 中使用/不使用 float 进行除法