Visual C ++完美转发编译错误

时间:2018-05-14 11:10:53

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

为什么这不能在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 &)': 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

1 个答案:

答案 0 :(得分:5)

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

  1. Foo的复制构造函数不是noexcept,它没有移动构造函数。
  2. Bar隐式声明的移动构造函数也不是noexcept,因为它需要为Foo数据成员调用前面提到的复制构造函数。
  3. emplace_back可能会重新分配,并且由于Bar似乎是可复制的,因此重新分配将复制现有元素以保留强大的异常安全保证。
  4. 根据实施情况,可以从const或非const Bar左值进行此复制。
  5. 您的无约束构造函数模板劫持了从非常量Bar左值的复制。
  6. 爆炸和烟花随​​之而来。
  7. 修复是约束构造函数模板,以便它不会被劫持。例如:

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