Any reason why this does not compile in Visual Studio C++? I'm using Visual Studio 2017 15.7.1. It compiles in clang and 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);
}
The error is error C2664: 'Foo::Foo(const Foo &)': cannot convert argument 1 from 'Bar' to 'int'
See https://godbolt.org/g/bKb34v
EDIT: I've submitted this issue here: https://developercommunity.visualstudio.com/content/problem/252470/perfect-forwarding-compiler-bug.html
This is your bug, not MSVC's.
Foo's copy constructor is not noexcept and it has no move constructor.Bar's implicitly declared move constructor is not noexcept either, because it needs to call the aforementioned copy constructor for the Foo data member.emplace_back may reallocate, and since Bar appears copyable, that reallocation will copy the existing elements to preserve the strong exception safety guarantee.const or non-const Bar lvalue.Bar lvalue.The fix is to constrain the constructor template so that it doesn't hijack. For example:
template <class... Args,
class = std::enable_if_t<std::is_constructible_v<Foo, Args...>>>
Bar(Args&&... args)
: foo(std::forward<Args>(args)...) {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With