I'm getting a compile error in Visual Studio 2015 when I try to declare a variable of class, when that classes uses the PIMPL pattern.
Foo.h:
#pragma once
class Foo
{
public:
Foo(const std::wstring& str,
const std::vector<std::wstring>& items);
~Foo();
private:
struct Impl;
std::unique_ptr<Impl> pimpl;
};
Foo.cpp:
#include "stdafx.h"
#include "Foo.h"
struct Foo::Impl
{
public:
Impl(const std::wstring& str,
const std::vector<std::wstring>& items);
std::wstring str_;
std::vector<std::wstring> items_;
};
Foo::Foo(const std::wstring& str,
const std::vector<std::wstring>& items)
: pimpl(std::make_unique<Impl>(str, items))
{
}
Foo::~Foo() = default;
Foo::Impl::Impl(const std::wstring& str,
const std::vector<std::wstring>& items)
: str_(str),
items_(items)
{
}
If I declare a variable of type Foo
using the traditional syntax, it compiles fine:
Foo f(L"Hello", std::vector<std::wstring>());
However, if I declare it using auto
, then I get a compile error:
auto f2 = Foo { L"Goodbye", std::vector<std::wstring>() };
error C2280: 'Foo::Foo(const Foo &)': attempting to reference a deleted function
note: compiler has generated 'Foo::Foo' here
I understand that the copy constructor for Foo
should be deleted, since unique_ptr
can't be copied. However, it was my understanding that when declaring variables in this way, the result would be either moved into the variable or just set the value into the variable directly.
The second line compiles fine when using Visual Studio 2013. I checked the breaking changes in Visual Studio 2015, but I didn't see anything there that would indicate why this started failing.
Am I doing something wrong, or can this syntax not be used with non-copyable types?
The move constructor is not implicitly declared, because you have a user-declared destructor (see [class.copy]/(9.4)). However, the copy constructor is clearly deleted, since unique_ptr
can't be copied.
You can explicitly declare the move constructor as defaulted.
Because the class contains a std::unique_ptr
member the compiler can't generate a copy-constructor like it would normally do, which means your declaration and initialization (which invokes the copy-constructor) will not be possible.
You could solve it by making a move constructor for your class and mark it as default
.
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