clang的c++11支持可靠吗?

时间:2022-02-26 17:26:23

I ran into an interesting issue when trying to mix clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn, Target: x86_64-apple-darwin14.0.0), c++11 and CGAL (via MacPorts).

当我试图混合clang时,我遇到了一个有趣的问题(clang-600.0.56)(基于LLVM 3.5svn,目标是:x86_64-apple-darwin14.0.0), c++11和CGAL(通过MacPorts)。

It seems that whether or not I call std::vector<>::reserve will determine whether my program will even compile.

无论我是否调用std::vector<>::reserve将决定我的程序是否会编译。

I've trimmed down the problem into a minimal example (as minimal as CGAL examples get):

我将这个问题简化为一个最小的例子(最小的例子是CGAL示例):

#include <vector>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/AABB_triangle_primitive.h>

// CGAL::Epeck works fine, suggesting the problem is in CGAL::Epick
typedef CGAL::Epick Kernel;
typedef CGAL::Triangle_3<Kernel> Triangle_3; 
typedef typename std::vector<Triangle_3>::iterator Iterator;
typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
typedef typename Tree::Point_and_primitive_id Point_and_primitive_id;
typedef CGAL::Point_3<Kernel>    Point_3;

template <typename BKernel>
void A()
{
  const CGAL::AABB_tree<
    CGAL::AABB_traits<BKernel, 
      CGAL::AABB_triangle_primitive<BKernel, 
        typename std::vector<CGAL::Triangle_3<BKernel> >::iterator
      >
    >
  > tree;
  Point_and_primitive_id pp = tree.closest_point_and_primitive(Point_3());
}

void B()
{
  std::vector<Triangle_3> T;
#ifdef MAGIC
  T.reserve(0);
#endif
  return A<Kernel>();
}

Issuing:

发行:

clang++ -std=c++11 -c example.cpp -I/opt/local/include

This fails to compile. Giving errors like:

这无法编译。让这样的错误:

    In file included from example.cpp:1:
    In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:265:
    In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__bit_reference:15:
    In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:626:
    In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/utility:157:
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple:228:60: error: 
          no member named 'value' in 'std::__1::is_convertible<const CGAL::Point_3<CGAL::Epick> &,
          CGAL::Point_3<CGAL::Epick> >'
                                   is_convertible<_Tp0, _Up0>::value &&
                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tuple:242:14: note: 
          in instantiation of template class 'std::__1::__tuple_convertible_imp<true, std::__1::__tuple_types<const
          CGAL::Point_3<CGAL::Epick> &, const CGAL::Vector_3<CGAL::Epick> &>,
          std::__1::__tuple_types<CGAL::Point_3<CGAL::Epick>, CGAL::Vector_3<CGAL::Epick> > >' requested here
        : public __tuple_convertible_imp<tuple_size<typename remove_reference<_Tp>::type>::value ==

However, this does compile if I make this magic call to std::vector::reserve, issuing:

但是,如果我对std进行这个神奇的调用,它会编译:::

clang++ -std=c++11 -c example.cpp -I/opt/local/include -DMAGIC

or by disabling c++11

通过禁用或c + + 11

clang++ -c example.cpp -I/opt/local/include
  1. Is this a bug in CGAL or clang?
  2. 这是CGAL还是clang中的一个bug ?
  3. What explanation can there be for such erratic compiler behavior?
  4. 对于这种奇怪的编译器行为,有什么解释呢?
  5. Is there a clean way of avoiding this (hopefully without really changing the templating or function prototype set up as I need the solution to fit my larger project).
  6. 是否有一种干净的方法来避免这种情况(希望没有真正改变模板或函数原型,因为我需要解决方案来适应我的大项目)。

1 个解决方案

#1


5  

Since Apple's GCC is outdated (latest GPL v2 version from 2007, GCC 4.2.1) and not C++11 feature complete (hence the libstdc++ provided with it), you can install a more modern version of GCC through MacPorts (sudo port install gcc48 or sudo port install gcc49) and that will provide you a more modern version of libstdc++. I tested your code with:

因为苹果的GCC是过时的(从2007年最新GPL v2版本,GCC 4.2.1)准备而不是c++ 11功能完整的(因此libstdc + +提供),你可以安装一个更现代的GCC版本通过MacPorts(sudo端口安装gcc48或sudo端口安装gcc49),将提供你一个更现代的版本libstdc + +。我测试了你的代码:

/opt/local/bin/g++-mp-4.8 -std=c++11 -c example.cpp -I/opt/local/include

and it compiled succesfully.

编译成功。

If you prefer this solution and want a cleaner compiler call; you can set MacPorts' GCC as the default using gcc_select with the command (in my case for gcc48):

如果您更喜欢这个解决方案,并且需要一个更干净的编译器调用;您可以将MacPorts的GCC作为默认使用gcc_select使用命令(在我的例子中是gcc48):

sudo port select --set gcc mp-gcc48

only once. Then, you can compile it with just

只有一次。然后,您可以用just来编译它。

g++ -std=c++11 -c example.cpp -I/opt/local/include

in a new terminal session.

在一个新的终端会话中。

#1


5  

Since Apple's GCC is outdated (latest GPL v2 version from 2007, GCC 4.2.1) and not C++11 feature complete (hence the libstdc++ provided with it), you can install a more modern version of GCC through MacPorts (sudo port install gcc48 or sudo port install gcc49) and that will provide you a more modern version of libstdc++. I tested your code with:

因为苹果的GCC是过时的(从2007年最新GPL v2版本,GCC 4.2.1)准备而不是c++ 11功能完整的(因此libstdc + +提供),你可以安装一个更现代的GCC版本通过MacPorts(sudo端口安装gcc48或sudo端口安装gcc49),将提供你一个更现代的版本libstdc + +。我测试了你的代码:

/opt/local/bin/g++-mp-4.8 -std=c++11 -c example.cpp -I/opt/local/include

and it compiled succesfully.

编译成功。

If you prefer this solution and want a cleaner compiler call; you can set MacPorts' GCC as the default using gcc_select with the command (in my case for gcc48):

如果您更喜欢这个解决方案,并且需要一个更干净的编译器调用;您可以将MacPorts的GCC作为默认使用gcc_select使用命令(在我的例子中是gcc48):

sudo port select --set gcc mp-gcc48

only once. Then, you can compile it with just

只有一次。然后,您可以用just来编译它。

g++ -std=c++11 -c example.cpp -I/opt/local/include

in a new terminal session.

在一个新的终端会话中。