c++ - Visual C++完美转发编译报错

标签 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

最佳答案

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

  1. Foo 的复制构造函数不是 noexcept 并且它没有移动构造函数。
  2. Bar 隐式声明的 move 构造函数也不是 noexcept,因为它需要为 Foo 数据成员调用上述复制构造函数.
  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)...) {}

关于c++ - Visual C++完美转发编译报错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50328879/

相关文章:

c++ - 如何让 Visual Studio 2012 调用 native 64 位 Visual C++ 编译器而不是 32 位 x64 交叉编译器?

c++ - 将 MSVS 2010 项目转换为 MSVS 2012 RC 但出现错误 "The C++ standard doesn' t 为此类型提供哈希”

actionscript-3 - AS3中的突破游戏错误#2007

java - 无法将原语分配给 Eclipse 中的对象数组

c++ - 代码::积木问题

c# - Npgsql Entityframework - 看不到 ADO.net 实体数据模型的 Postgres 提供程序

c++ - c++读写同一个文件

c++ - 如何告诉编译器使用 C++ 2011 _in_code_ 而不是标志

c# - 如何在 VS 2017 for ASP.NET Core 项目中按路径段嵌套文件

asp.net - Azure Functions 项目在 Azure Functions 扩展升级后出现 System.ValueTuples 错误