在libc中的内联命名空间中转发声明类的可移植方法是什么?
作者:互联网
仅当我将-stdlib = libc指定为clang时,以下代码才会编译:
namespace std {
class mutex;
}
void f(std::mutex &x);
#include <mutex>
void f(std::mutex &x) { }
> http://goo.gl/Uqpv6f(gcc.godbolt.org)
note: candidate found by name lookup is ‘std::__1::mutex’
我明白什么是:: __ 1那里,
> Where does the __1 symbol come from when using LLVM’s libc++?
但在我看来,libc打破了C标准定义的API:
> http://en.cppreference.com/w/cpp/thread/mutex(嗯,这不是真正的标准…)
应该可以转发声明std :: mutex,因为它应该直接驻留在std下,不应该吗?
请注意,编译阶段而不是链接阶段失败.所以我不认为我的问题的答案应该是“因为libc使用了与GNU libstdc不同的ABI ……”
解决方法:
but to my eyes, libc++ breaks the API defined by the C++ standard:
实际上,它没有.该标准在[contents]中指定:
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将互斥锁放入内联命名空间__1.请注意,有good reasons个需要内联命名空间,通常作为用户,您甚至不关心它们是否存在.
对于您的特定问题,您仍然可以使用libc向前声明std :: mutex …您只需要包含所有命名空间(有关如何检测-std = libc,请参阅this question):
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>
标签:c,c11,clang,libc-2 来源: https://codeday.me/bug/20190824/1705843.html