编译Assimp时出现多个-fpermissive错误,求解决方法
Assimp编译错误:std命名空间模板特化问题的解决
问题场景
通过git clone https://github.com/assimp/assimp.git下载Assimp源码,执行CMake时添加-DASSIMP_WARNINGS_AS_ERRORS=OFF参数规避stb_i.h中未使用函数的编译问题,但执行sudo make时出现以下编译错误:
/home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.cpp:226:13: error: specialization of ‘template<class _Tp> struct std::hash’ in different namespace [-fpermissive] struct std::hash<Vertex> { ^ In file included from /usr/include/c++/5/bits/basic_string.h:5471:0, from /usr/include/c++/5/string:52, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/ostream:38, from /usr/include/c++/5/iterator:64, from /home/kshaugnnessy/Downloads/engine/assimp/contrib/utf8cpp/source/utf8/core.h:31, from /home/kshaugnnessy/Downloads/engine/assimp/contrib/utf8cpp/source/utf8/checked.h:31, from /home/kshaugnnessy/Downloads/engine/assimp/include/../contrib/utf8cpp/source/utf8.h:31, from /home/kshaugnnessy/Downloads/engine/assimp/include/assimp/types.h:79, from /home/kshaugnnessy/Downloads/engine/assimp/include/assimp/Importer.hpp:60, from /home/kshaugnnessy/Downloads/engine/assimp/include/assimp/GenericProperty.h:52, from /home/kshaugnnessy/Downloads/engine/assimp/code/Common/BaseProcess.h:46, from /home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.h:48, from /home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.cpp:48: /usr/include/c++/5/bits/functional_hash.h:58:12: error: from definition of ‘template<class _Tp> struct std::hash’ [-fpermissive] struct hash; ^ /home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.cpp:235:13: error: specialization of ‘template<class _Tp> struct std::equal_to’ in different namespace [-fpermissive] struct std::equal_to<Vertex> { ^ In file included from /usr/include/c++/5/string:48:0, from /usr/include/c++/5/bits/locale_classes.h:40, from /usr/include/c++/5/bits/ios_base.h:41, from /usr/include/c++/5/ios:42, from /usr/include/c++/5/ostream:38, from /usr/include/c++/5/iterator:64, from /home/kshaugnnessy/Downloads/engine/assimp/contrib/utf8cpp/source/utf8/core.h:31, from /home/kshaugnnessy/Downloads/engine/assimp/contrib/utf8cpp/source/utf8/checked.h:31, from /home/kshaugnnessy/Downloads/engine/assimp/include/../contrib/utf8cpp/source/utf8.h:31, from /home/kshaugnnessy/Downloads/engine/assimp/include/assimp/types.h:79, from /home/kshaugnnessy/Downloads/engine/assimp/include/assimp/Importer.hpp:60, from /home/kshaugnnessy/Downloads/engine/assimp/include/assimp/GenericProperty.h:52, from /home/kshaugnnessy/Downloads/engine/assimp/code/Common/BaseProcess.h:46, from /home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.h:48, from /home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.cpp:48: /usr/include/c++/5/bits/stl_function.h:332:12: error: from definition of ‘template<class _Tp> struct std::equal_to’ [-fpermissive] struct equal_to; ^ code/CMakeFiles/assimp.dir/build.make:747: recipe for target 'code/CMakeFiles/assimp.dir/PostProcessing/JoinVerticesProcess.cpp.o' failed make[2]: *** [code/CMakeFiles/assimp.dir/PostProcessing/JoinVerticesProcess.cpp.o] Error 1 CMakeFiles/Makefile2:203: recipe for target 'code/CMakeFiles/assimp.dir/all' failed make[1]: *** [code/CMakeFiles/assimp.dir/all] Error 2 Makefile:135: recipe for target 'all' failed make: *** [all] Error 2
错误原因
C++标准规定:特化std命名空间中的模板时,必须将特化代码放在std命名空间内部。当前Assimp源码直接在全局命名空间下写struct std::hash<Vertex>,这种写法不符合标准,GCC 5及以上版本会严格检查并报错。
解决方法
方法一:修改源码中的模板特化写法
- 打开文件
/home/kshaugnnessy/Downloads/engine/assimp/code/PostProcessing/JoinVerticesProcess.cpp - 找到错误对应的两处模板特化代码(行226和235),将原有代码:
修改为:struct std::hash<Vertex> { // 原实现逻辑 }; struct std::equal_to<Vertex> { // 原实现逻辑 };namespace std { template<> struct hash<Vertex> { size_t operator()(const Vertex& v) const { // 保留原有的哈希计算逻辑 } }; template<> struct equal_to<Vertex> { bool operator()(const Vertex& a, const Vertex& b) const { // 保留原有的顶点比较逻辑 } }; } // namespace std - 保存文件后,重新执行
sudo make即可完成编译。
方法二:切换到Assimp稳定分支
如果不想修改源码,可以切换到Assimp的稳定版本分支(比如v5.2.x),这类分支通常已经修复了旧编译器的兼容性问题:
cd assimp git checkout v5.2.5 # 可替换为最新稳定版本号 rm -rf build && mkdir build && cd build cmake -DASSIMP_WARNINGS_AS_ERRORS=OFF .. sudo make
内容的提问来源于stack exchange,提问作者Kevin Shaughnessy
相关产品推荐
相关产品推荐

