jww*_*jww 4 unique-ptr llvm-clang c-preprocessor c++11 c++03
尝试unique_ptr在 Apple 平台上使用时遇到编译错误-std=c++11:
$ make
c++ -std=c++11 -DNDEBUG -g2 -O3 -fPIC -march=native -Wall -Wextra -pipe -c 3way.cpp
In file included ...
./smartptr.h:23:27: error: no type named 'unique_ptr' in namespace 'std'
using auto_ptr = std::unique_ptr<T>;
~~~~~^
./smartptr.h:23:37: error: expected ';' after alias declaration
using auto_ptr = std::unique_ptr<T>;
Run Code Online (Sandbox Code Playgroud)
根据 Marshall Clow 的说法,我认为他是Clang 和 Apple的C++ 标准库专家:
技术报告 #1 (TR1) 是 C++03 标准的一组库添加。代表它们不是“官方”标准的一部分,它们被放置在命名空间 std::tr1 中。
在 c++11 中,它们正式成为标准的一部分,并存在于命名空间 std 中,就像向量和字符串一样。包含文件也不再位于“tr1”文件夹中。
带走:
LIBCPP_VERSION检测libc++现在,这就是我所拥有的smartptr.h:
#include <memory>
// Manage auto_ptr warnings and deprecation in C++11
// Microsoft added template aliases to VS2015
#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif // C++11
Run Code Online (Sandbox Code Playgroud)
我认为最后要检查的是__APPLE__定义,这里是:
$ c++ -x c++ -dM -E - < /dev/null | grep -i apple
#define __APPLE_CC__ 6000
#define __APPLE__ 1
#define __VERSION__ "4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)"
#define __apple_build_version__ 5030040
Run Code Online (Sandbox Code Playgroud)
为什么我error: no type named 'unique_ptr' in namespace 'std'在使用时收到了-std=c++11?
我认为这是四个测试用例。它尝试从以下的交叉产品中练习四种配置:{C++03,C++11} x {libc++,libstdc++}。
这里是测试驱动程序。请务必在 OS X 上对其进行测试,以便在 2015 年获得 TR1 命名空间的全部效果。
$ cat test-clapple.cxx
// c++ -c test-clapple.cxx
// c++ -stdlib=libc++ -c test-clapple.cxx
// c++ -std=c++11 -c test-clapple.cxx
// c++ -std=c++11 -stdlib=libc++ -c test-clapple.cxx
#include <memory>
// Manage auto_ptr warnings and deprecation in C++11
#if (__cplusplus >= 201103L) || (_MSC_VER >= 1900)
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif // C++11
int main(int argc, char* argv[])
{
return argc;
}
Run Code Online (Sandbox Code Playgroud)
CFE 开发人员特别告诉我使用该代码;
不,他们没有。如果你想使用shared_ptr,他们告诉你做类似的事情,因为对于 C++03 <tr1/memory>定义std::tr1::shared_ptr和对于 C++11<memory>定义std::shared_ptr。
但你没有使用shared_ptr. 如果你想使用,auto_ptr那么它只是std::auto_ptr, 无处不在,它总是在<memory>.
我认为你误解了马歇尔的评论,你把事情复杂化了。您引用的内容('在 c++11 中,它们正式成为标准的一部分,并且存在于命名空间 std 中,就像向量和字符串一样。包含文件也不再存在于“tr1”文件夹中。')是不是 Apple 特定的或 Clang 特定的,它适用于所有编译器。但是因为auto_ptr从来不是 TR1 的一部分,而且 TR1<tr1/memory>的内容现在在 namespace 中是无关紧要的std,因为您尝试使用的内容从未包含在 TR1 中。
您根本不应该在这里使用 TR1 。
# include <memory>
// Manage auto_ptr warnings and deprecation in C++11
#if (__cplusplus >= 201103L)
template<typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif // C++11
Run Code Online (Sandbox Code Playgroud)
这对于现代编译器来说应该是正确的,但不适用于 XCode 附带的愚蠢配置,它是 Clang 的现代版本,支持 C++11 和来自 GCC 4.2 的 libstdc++,它已有近十年的历史并且没有支持unique_ptr。
为了处理默认的 OS X 工具链,这是有效的:
#include <memory>
#if __cplusplus >= 201103L
# ifdef __clang__
# if __has_include(<forward_list>)
// either using libc++ or a libstdc++ that's new enough to have unique_ptr
# define HAVE_UNIQUE_PTR 1
# endif
# else // not clang, assume unique_ptr available
# define HAVE_UNIQUE_PTR 1
# endif
#endif
#ifdef HAVE_UNIQUE_PTR
template<typename T> using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif
Run Code Online (Sandbox Code Playgroud)
这是通过使用 of<forward_list>作为标准库 clang 是否正在使用支持的指标来工作的std::unique_ptr。
如果 clang 使用 libc++ 作为其标准库,则所有版本都支持unique_ptr并提供<forward_list>,因此测试通过。
如果 clang 使用的是 libstdc++,则是否unique_ptr支持取决于 libstdc++ 版本。unique_ptr加入与libstdc ++在GCC 4.3,这是添加的同一版本<forward_list>,因此,如果该标头可用,则unique_ptr也将如此。如果您将 clang 与 Apple 工具链(来自 GCC 4.2)附带的古老 libstdc++ 一起使用,unique_ptr则不支持,但也不支持<forward_list>,因此测试失败,您可以使用auto_ptr。
这应该适用于在野外发现的任何 GCC/libstdc++、Clang/libc++ 或 Clang/libstdc++ 组合。我不知道 VC++/Dinkumware 和 Clang/Dinkumware 需要什么,从您的回答看来,您可能只需将第一个条件更改为:
#if __cplusplus >= 201103L || _MSC_VER >= 1600
Run Code Online (Sandbox Code Playgroud)