【问题标题】:Possible bug in libc++?libc++ 中可能存在的错误?
【发布时间】:2012-10-21 10:50:42
【问题描述】:

以下代码用clang 3.1编译不上,使用libc++(不知道版本,目前Xcode自带的)。它适用于其他标准库。我的代码是否有错误,或者这是 libc++ 中的错误?

#include <map>
#include <string>
using namespace std;

struct A {
  A(const map<int, A>& m) {}
};

struct B {
  map<string, A> m;
};

我看到的错误在&lt;utility&gt;

/usr/lib/c++/v1/utility:241:64: No member named 'value' in 'std::__1::is_nothrow_copy_constructible<A>'

我试图进一步隔离它,但这是我发现的最小示例。有趣的是,当我在第二张地图中将string 替换为int 时它可以工作(当我在第一张地图中将int 替换为string 时):

map<string, A> m; // Does not work
map<int, A> m; // Works

【问题讨论】:

  • @hvd XCode 4.5 附带的 Clang 版本将自己标识为 Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
  • 呸。感谢那。我会删除我的评论,因为它没有帮助。我认为 Apple 在没有明确表示他们已经这样做的情况下偏离了 clang 版本号是一个错误。
  • 我在这里遗漏了什么还是仅仅因为您的A 不是默认可构造的?
  • 添加A() {} 或/和A(const A&amp;) {} 不会使错误消失。正如我所说,它可以与 libstdc++(甚至是当前 debian 的 libc++)一起编译。
  • +1 完整的最小示例。 SSCCE.ORG

标签: c++ c++11 std libc++


【解决方案1】:

这并不完全是一个错误,我会向你解释原因:

1997 年,在 C++ 标准完成前不久,标准化委员会收到了一个疑问:是否可以创建类型不完整的标准容器?委员会花了一段时间才理解这个问题。这样的事情甚至意味着什么,你到底为什么想要这样做?委员会最终解决了这个问题并提出了这个问题的答案。 (这样您就不必跳到最后,答案是“否”。)但是这个问题比答案更有趣:它指向了一种有用的、没有充分讨论的编程技术。标准库不直接支持该技术,但可以使两者共存。

当您声明 const std::map&lt;int, A&gt;&amp; 时,A 仍然不完整,并且标准不强制实现者为不完整类型提供支持,因此如果您确实需要它并且可以选择使用 boost,您可以更改您的容器并在不支持此功能的编译器中使用 boost::container 代替标准容器。

【讨论】:

  • 这是否意味着示例中不需要struct B
  • 嗯,这仍然不能解释某些行为。删除struct B 使其工作,还将映射键的类型从int 更改为string 使其编译正常。
  • 在你的代码中struct B负责实例化struct A,删除它,以某种方式删除A,删除B并尝试在main中实例化A并查看结果自己:)
  • 我明白了。如果两张地图相同,它会起作用吗?
  • 另外,我找到了你第一段的出处。如果您在答案中将其链接起来会有所帮助;)drdobbs.com/the-standard-librarian-containers-of-inc/184403814