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

时间:2016-03-02 03:06:42

标签: c++ c++11 clang libc++

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

namespace std {
  class mutex;
}

void f(std::mutex &x);

#include <mutex>

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

注意:通过名称查找找到的候选人是&#39; std :: __ 1 :: mutex&#39;

我了解::__1那里是什么,

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

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

请注意,编译阶段而非链接阶段失败。所以我不认为我的问题的答案应该是&#34;因为libc ++使用了与GNU libstdc ++不同的ABI ......&#34;

1 个答案:

答案 0 :(得分:6)

  

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

实际上,它没有。该标准在[contents]中指定:

  

未指定是否在特定的地方声明了名称   命名空间直接在该命名空间或该命名空间内的内联命名空间中声明。

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

对于您的具体问题,您可以仍然使用libc ++转发声明std::mutex ...您只需要包含所有命名空间(有关如何检测,请参阅this question -std =的libc ++):

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

但是,来自[namespace.std]:

  

如果C ++程序向名称空间std或a添加声明或定义,则它的行为是未定义的   命名空间std中的命名空间,除非另有说明。

前向声明仍然是一个声明,所以即使上面的内联命名空间占用的版本也是未定义的行为。所以更喜欢直接这样做:

#include <mutex>