为什么这不能在 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 的。
Foo
的复制构造函数不是noexcept
并且它没有移动构造函数。Bar
隐式声明的 move 构造函数也不是noexcept
,因为它需要为Foo
数据成员调用上述复制构造函数.emplace_back
可以重新分配,并且由于Bar
看起来可复制,重新分配将复制现有元素以保留强大的异常安全保证。- 根据实现的不同,可以从
const
或非const
Bar
左值进行复制。 - 您的无约束构造函数模板劫持了从非常量
Bar
左值进行的复制。 - 接着是爆炸和烟花。
解决方法是限制构造函数模板,使其不会被劫持。例如:
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/