I am getting a compilation error on this C++11 code but I dont know why. This is the code:
#include <condition_variable>
class NonCopiableClass
{
std::condition_variable condition_;
};
struct NonCopiableStruct
{
std::condition_variable condition_;
};
class Test
{
public:
Test() :
myClass{},
myStruct{}
{};
private:
NonCopiableClass myClass;
NonCopiableStruct myStruct;
};
Visual Studio 2015 fails with the following error:
error C2280: 'std::condition_variable::condition_variable(const std::condition_variable &)': attempting to reference a deleted function 1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\mutex(550): note: see declaration of 'std::condition_variable::condition_variable'.
If I change the Test constructor
to not use C++11 uniform initialization of the Struct
it compiles OK.
Test() :
myClass{},
myStruct() // <--- CHANGE
{};
I am not getting why for Struct
type uses copy constructor but the Class
seems OK. It only happends with Struct
having non-copiable members.
I also noted that if I init the Struct
outside of the Test Class
member initializer list It works:
int main()
{
NonCopiableStruct a{};
return 0;
}
Any idea Why is this code failing?. What is going on under the hood? What is the difference between myClass
initialization and myStruct
initialization?. Why it won't compile if used on the class member initializer list
but is it okay I use it outside? I have tried on GCC
and it seems to be okay.
This seems like a MSVC bug. The difference is that the struct
version is an aggregate, and the class
version is not (on account of the default private access specifier).
The class version is value initialized by {}
. The struct version is aggregate initialized. A conforming compiler should just list initialize condition_
with {}
, because you didn't provide an initializer for it.
But MSVC seems to be stumbling on the fact that members of an aggregate are copy initialized from the corresponding initializer in the initializer list. It seems to check for the copy c'tor, even if it isn't supposed to actually use it.
This is further supported by the fact it knows what to do when an object of the same type is initialized outside of a member initializer list.