在 libc++ 的内联命名空间中转发声明 类 的可移植方式是什么?

What is the portable way to forward-declare classes in an inline namespace in libc++?

仅当我将 -stdlib=libc++ 指定为 clang++ 时,以下代码才不会编译:

namespace std {
  class mutex;
}

void f(std::mutex &x);

#include <mutex>

void f(std::mutex &x) { }

note: candidate found by name lookup is 'std::__1::mutex'

我明白::__1那里是什么,

但在我看来,libc++ 打破了 C++ 标准定义的 API:

应该 可以转发声明 std::mutex 因为它应该直接位于 std 之下,不是吗?

请注意编译阶段失败,而不是链接阶段失败。所以我认为我的问题的答案不应该是 "because libc++ employs a different ABI from GNU libstdc++..."

but to my eyes, libc++ breaks the API defined by the C++ standard:

其实不然。标准在[内容]中规定:

It is unspecified whether names declared in a specific namespace are declared directly in that namespace or in an inline namespace inside that namespace.

libc++允许将mutex放入inline namespace __1。请注意,有 good reasons 需要内联名称空间,通常作为用户,您甚至不关心它们是否存在。

对于您的具体问题,您可以仍然使用 libc++ 向前声明 std::mutex...您只需要包括所有名称空间(参见 如何检测 -std=libc++):

namespace std {
#ifdef _LIBCPP_VERSION
    inline namespace __1 {
        struct mutex;
    }
#else
    struct mutex;
#endif
}

但是,来自 [namespace.std]:

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified.

前向声明仍然是一个声明,因此即使是上述说明内联命名空间的版本也是未定义的行为。所以更喜欢直接的方式:

#include <mutex>