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

马丁尼

为什么在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

TC

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

  1. Foo的copy构造函数不是noexcept,并且没有move构造函数。
  2. Bar的隐式声明的move构造函数也不noexcept是,因为它需要为Foo数据成员调用前面提到的copy构造函数
  3. emplace_back可以重新分配,并且由于Bar看上去是可复制的,所以重新分配将复制现有元素,以保留强大的异常安全保证。
  4. 根据实现的不同,可以从一个const或非const Bar左值进行复制
  5. 您不受约束的构造函数模板会劫持从非常量Bar左值进行的复制
  6. 爆炸和烟火随之而来。

解决方法是限制构造函数模板,以使其不会被劫持。例如:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章