【问题标题】:Visual C++ perfect forwarding compile errorVisual C++完美转发编译错误
【发布时间】:2018-05-14 11:10:53
【问题描述】:

为什么这不能在 Visual Studio C++ 中编译?我正在使用 Visual Studio 2017 15.7.1。它在 clang 和 g++ 中编译:

#include <utility>
#include <vector>

struct Foo {
    Foo(int x) {}
    Foo(Foo const& b) {}
};

struct Bar {
    template <class... Args>
    Bar(Args&&... args)
        : foo(std::forward<Args>(args)...) {}

    Foo foo;
};

void test() {
    std::vector<Bar> v;
    v.emplace_back(123);
}

错误是error C2664: 'Foo::Foo(const Foo &amp;)': cannot convert argument 1 from 'Bar' to 'int'

https://godbolt.org/g/bKb34v

编辑:我在这里提交了这个问题:https://developercommunity.visualstudio.com/content/problem/252470/perfect-forwarding-compiler-bug.html

【问题讨论】:

  • 它看起来像一个编译器错误,你应该向 MS 报告这个
  • 已通过 MSVS 15.6.6 和工具集 v141 确认。但它使用工具集 v140 和 v140_xp 编译
  • 这是一个非常糟糕的错误

标签: c++ compiler-errors visual-studio-2017


【解决方案1】:

这是你的错误,不是 MSVC 的。

  1. Foo 的复制构造函数不是 noexcept,它没有移动构造函数。
  2. Bar 隐式声明的移动构造函数也不是noexcept,因为它需要为Foo 数据成员调用上述复制构造函数。
  3. emplace_back 可能会重新分配,并且由于 Bar 看起来是可复制的,因此重新分配将复制现有元素以保持强大的异常安全保证。
  4. 可以根据实现从const 或非const Bar 左值完成此复制。
  5. 您的无约束构造函数模板劫持了从非 const Bar 左值复制。
  6. 爆炸和烟花接踵而至。

解决方法是约束构造函数模板,使其不会劫持。例如:

template <class... Args, 
          class = std::enable_if_t<std::is_constructible_v<Foo, Args...>>>
Bar(Args&&... args)
    : foo(std::forward<Args>(args)...) {}

【讨论】:

    猜你喜欢
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多