【问题标题】:C++11 cmath functions not in std namespace for android NDK w/gcc-4.8 or clang 3.4android NDK w/gcc-4.8 或 clang 3.4 的 C++11 cmath 函数不在 std 命名空间中
【发布时间】:2014-05-20 07:38:29
【问题描述】:

在 C++11 之后,以前在全局命名空间中的各种 cmath 函数在包含 <cmath> 标头时被移动到 std 命名空间。

但是,在 gcc-4.8 和 clang-3.4 工具链中,android NDK 构建存在问题。

C++11 标志已正确指定,因为其他 c++11 细节如 unique_ptr 工作正常。

如果我尝试使用 std::roundstd::cbrt,编译器会说这些在 std:: 命名空间中不存在,它们应该 [1]。它们存在于全局命名空间中,但我不想使用它们。

这是一个已知问题吗?我忽略了什么吗?有解决办法吗?

[1]http://en.cppreference.com/w/cpp/header/cmath


  • 桌面版本使用 gcc-4.8.1 没有这个问题,我通过-Wall -Wextra -Wcast-align -Wcast-qual -fpermissive -Wconversion -Wdisabled-optimization -Weffc++ -Wfloat-equal -Wformat=2 -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wunreachable-code -Wunsafe-loop-optimizations -Wunused -Wvariadic-macros -Wwrite-strings -pedantic -pedantic-errors -Woverloaded-virtual -Wswitch-enum -Werror充分利用 gcc 警告

  • 相关的构建命令,尽其所能: /opt/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi/objs/main/__/android/jni/src/main.o.d -fpic -ffunction-sections -funwind-tables -fstack-protector -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Ijni/src/../android/jni/SDL/include -Ijni/src/../android/jni/SDL_image -Ijni/src/../android/jni/SDL_mixer -I/opt/bullet/bullet-2.82/include/bullet -I/opt/glm/glm-0.9.5.2 -I/opt/android-ndk-r9d/sources/android/cpufeatures -Ijni/SDL/include -Ijni/SDL_image -Ijni/SDL_image/external/jpeg-9 -Ijni/SDL_image/external/libpng-1.6.2 -Ijni/SDL_mixer -Ijni/SDL_mixer/external/libmodplug-0.8.8.4/src -Ijni/SDL_mixer/external/libmodplug-0.8.8.4/src/libmodplug -Ijni/SDL_mixer/external/smpeg2-2.0.0 -Ijni/SDL_mixer/external/libogg-1.3.1/include -Ijni/SDL_mixer/external/libvorbisidec-1.2.1 -I/opt/android-ndk-r9d/sources/cxx-stl/gnu-libstdc++/4.8/include -I/opt/android-ndk-r9d/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/include -I/opt/android-ndk-r9d/sources/cxx-stl/gnu-libstdc++/4.8/include/backward -Ijni/src -DANDROID -fno-strict-aliasing -D_REENTRANT -DGLM_FORCE_RADIANS -isystem /opt/glm/glm-0.9.5.2 -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -fexceptions -frtti -I/opt/android-ndk-r9d/platforms/android-19/arch-arm/usr/include -c jni/src/../android/jni/src/main.cpp -o ./obj/local/armeabi/objs/main/__/android/jni/src/main.o

【问题讨论】:

  • 另请参阅error: 'log2' is not a member of 'std',了解 GCC 不将 C99 数学函数导入 std 命名空间的原因之一。引用的问题是关于较旧的 PowerMac G5,我不确定它与现代 Android 的交互情况如何。

标签: android c++ c++11 stl android-ndk


【解决方案1】:

这似乎是 Android 上 C++11 支持的一个已知问题。有is a known issue,表示缺少很多套路:

使用-std=c++11gnustl_shared 编译c++ 代码时,<cmath> 标头没有提供许多 C99 数学函数。

您最好假设只有有限的 c++ 库子集可用于 android - 这似乎在 ndk 的 docs/ 中的 CPLUSPLUS-SUPPORT.html 文件中指出。

当我有的时候提醒你:

APP_STL := c++_static

在我的Application.mk

LOCAL_CPPFLAGS  := -std=c++11

在我的Android.mk 中,使用std::cbrtstd::round 的文件编译干净;但它是针对静态 LLVM libc++,而不是针对 gnu 标准库。

【讨论】:

  • 出于某种原因,我阅读了旧版本的 CPLUSPLUS-SUPPORT.html,它没有列出 LLVM libc++。这解决了我遇到的几个问题。最值得注意的是 gnustl GPLv3 问题。通常我会在接受答案之前等待几周,但我看不出还有什么可以添加的。谢谢你。我最终选择了 c++_shared,它也没有任何问题。
【解决方案2】:

如果确实缺少函数,您必须自己编写它们(或从其他实现中复制它们)。

在 Android NDK 中,一些功能似乎存在,但就在namespace std 之外。我通过将函数 round 添加到 namespace std 来解决 round 函数的相同问题,该函数只是从全局范围内回退到 round 函数。

namespace std
{
    inline int round(float x)
    {
        return ::round(x);
    }
}

如果您想以可移植的方式使用它,则必须使用预处理器宏来保护它。

【讨论】:

  • 另请参阅error: 'log2' is not a member of 'std',了解 GCC 不将 C99 数学函数导入 std 命名空间的原因之一。引用的问题是关于较旧的 PowerMac G5,我不确定它与现代 Android 的交互情况如何。
猜你喜欢
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 2014-10-26
相关资源
最近更新 更多