【问题标题】:Clang only: A pair<path, path> can be emplaced into a vector; so can a pair<unique_ptr, unique_ptr>; but NOT pair<path, unique_ptr>: Why?仅 Clang:pair<path, path> 可以放置到向量中;一对<unique_ptr, unique_ptr>也可以;但不是对<path, unique_ptr>:为什么?
【发布时间】:2014-01-02 05:32:02
【问题描述】:

我有以下三个 sn-ps 代码来演示一个易于重现的问题。

using namespace boost::filesystem;
using namespace std;

int main()
{

    path dummy_path;

    // Snippet 1
    // Two paths
    // Succeeds
    //
    // vector<pair<path, path>> myvec;
    // myvec.emplace_back(dummy_path, dummy_path);

    // Snippet 2
    // Two unique_ptr's
    // Succeeds
    //
    // vector<pair<unique_ptr<int>, unique_ptr<int>>> myvec;
    // myvec.emplace_back(unique_ptr<int>(new int(13)), unique_ptr<int>(new int(12)));

    // Snippet 3
    // A path and a unique_ptr.
    //
    // **FAILS** on Clang, succeeds in Visual Studio
    //
    vector<pair<path, unique_ptr<int>>> myvec;
    myvec.emplace_back(dummy_path, unique_ptr<int>(new int(12)));

}

这是 Clang 上的编译器错误:

error: call to implicitly-deleted copy constructor of 'std::__1::unique_ptr&lt;int, std::__1::default_delete&lt;int&gt; &gt;'(显然是指该对的第二个成员,unique_ptr)。

似乎由于某种原因,指示的失败案例导致调用该对的复制构造函数,而不是移动构造函数。

这是 OS X 10.8.5 上的 Clang 5.0.2。 (以及 VS 11.0.60610.01 Update 3 在 Windows 7 64 位上。)

在我的实际应用中,数据类型更复杂,但错误归结为这个问题中描述的错误。

我的问题是双重的:为什么指示的案例在 Clang 上失败,即使涵盖两种数据类型的其他两个案例成功了?

然而,也许更重要的是:我可以做些什么来解决这个问题?因为我的实际应用程序更复杂,所以我无法选择不执行 emplace(或类似的操作)将给定对放入向量中 - 但如果有任何其他方法可以解决这个 Clang 问题以将该对放入该向量中,我会非常高兴。

【问题讨论】:

  • myvec.emplace_back(std::move(dummy_path), unique_ptr&lt;int&gt;(new int(12))); 工作吗?
  • @jrok - 我试过了(并且会包含在问题中,但希望问题尽可能简单)。答案:不。在pathunique_ptr 或两者周围添加std::move(),仍然失败。
  • Coliru 的 Clang 版本编译良好。
  • @jrok - 这是有希望的。也许它是一个编译器标志。我要开始挖了。
  • @jrok 有了以下编译器标志,问题就出现了:-x c++ -arch x86_64 -std=gnu++11 -stdlib=libc++。见coliru.stacked-crooked.com/a/5b90bf49e93c6535

标签: c++ c++11 vector compiler-errors clang


【解决方案1】:

这是 libc++ 中的一个错误,抱歉。它已固定在树干顶端。我相信您可以通过在编译命令中添加以下内容来解决它:

-D_LIBCPP_TRIVIAL_PAIR_COPY_CTOR

【讨论】:

  • 谈到快速响应 - 问题在报告后 2 小时内得到解决。恭喜,谢谢。
  • 这里是错误报告的链接。 llvm.org/bugs/show_bug.cgi?id=18249#c1(任何有兴趣的人)。
  • 我的话模棱两可。它已经固定在树干的顶端。我希望我建议的解决方法对您有用。
  • 不幸的是,这里的预处理器标志似乎不起作用。在进行完全清理以删除任何缓存的预处理文件并尝试编译有问题的文件(使用以下观察到的(相关)命令行:clang++ -c -pipe -std=c++11 -stdlib=libc++ -D_LIBCPP_TRIVIAL_PAIR_COPY_CTOR -g -gdwarf-2 -isysroot -std=c++11 -stdlib=libc++(是的,两个标志是重复的))-不幸的是,相同报错。
  • 那么恐怕你唯一的选择就是检查树干末端的 libc++ (libcxx.llvm.org),然后放 -nostdinc++ -I/include在命令行上。这不需要重建 dylib。
【解决方案2】:

问题来自 libc++ 标准库,因为它内部的 pair 构造函数要少得多。

即libstd++ 有以下构造函数:

template<class _U2, class = typename
       enable_if<is_convertible<_U2, _T2>::value>::type>
constexpr pair(const _T1& __x, _U2&& __y)
: first(__x), second(std::forward<_U2>(__y)) { }

它允许在 Linux 上编译您的示例(使用 clang++)。但是libc++只有:

pair(const pair&) = default;
pair(pair&&) = default;
constexpr pair();
pair(const T1& x, const T2& y);                          // constexpr in C++14
template <class U, class V> pair(U&& x, V&& y);          // constexpr in C++14
template <class U, class V> pair(const pair<U, V>& p);   // constexpr in C++14
template <class U, class V> pair(pair<U, V>&& p);        // constexpr in C++14
template <class... Args1, class... Args2>
    pair(piecewise_construct_t, tuple<Args1...> first_args,
         tuple<Args2...> second_args);

我猜,pair(const T1&amp; x, const T2&amp; y); 被应用是因为第一个参数是非右值引用。


“硬核”解决方案是手动将此构造函数放置在系统库中。 pairutility 文件中定义。如果您希望能够在其他地方编译您的代码,您可以将修改后的 libc++ 捆绑到您的项目中 - 这没什么大不了的,真的。

【讨论】:

  • 谢谢。问题是,在 Xcode 中设置什么设置来构建示例代码?在过去的一个小时里,我一直在尝试的任何组合都不起作用。
  • 非常感谢。如果您能提及将修改后的libc++ 捆绑到项目中的过程中的第一步或第二步,我将不胜感激。我在 Windows 上的经验要丰富得多。
  • @DanNissenbaum 我对 XCode 不熟悉,但您可以从这个页面开始:libcxx.llvm.org“获取并参与其中!”部分- 该库由一个命令构建。然后,您只需要在 XCode 项目中正确设置编译标志,即可与您的库而不是系统库挂钩。
  • @DanNissenbaum 实际上,运送您自己的 STL 库并用它构建 - 是关于 SO 的另一个问题 :)
  • 对于不接受您的回答,我深表歉意(特别是因为您将其隔离为 libc++ 错误)。但是,我确实向 libc++ 项目提交了错误报告,当 libc++ 项目的 Howard Hinnant 在两个小时内真正解决了问题时,我对接受谁的答案感到困惑。我希望我能接受这两个,我感谢你隔离了这个错误。最后,我觉得霍华德在图书馆本身的快速修复保证了被接受的答案。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 2014-07-21
  • 2021-05-16
  • 1970-01-01
  • 2014-03-10
  • 1970-01-01
  • 2019-11-30
相关资源
最近更新 更多