This code, with a const A& a
member in B
, where A
has a deleted copy constructor, doesn't compile in GCC 4.8.1, but it works OK in clang 3.4:
class A {
public:
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
};
class B{
public:
B(const A& a)
: a{a}
{ }
private:
const A& a;
};
int main()
{
A a{};
B b{a};
}
Which one of the compilers is right?
The error in GCC is:
prog.cpp: In constructor ‘B::B(const A&)’:
prog.cpp:11:14: error: use of deleted function ‘A::A(const A&)’
: a{a}
^
prog.cpp:4:5: error: declared here
A(const A&) = delete;
^
Ideone: http://ideone.com/x1CVwx
Your example can be reduced to
class A {
public:
A() = default;
A(const A&) = delete;
A& operator=(const A&) = delete;
};
int main()
{
A a{};
A const& ar1(a);
A const& ar2{a}; // fails on gcc 4.8
}
The initialization of ar2
fails on gcc-4.8 with the error
error: use of deleted function ‘A::A(const A&)’
It compiles cleanly on clang3.4 and gcc4.9. This is the result of the resolution to CWG issue 1288.
N3337 contains the following language for list-initialization:
§8.5.4/3 [dcl.init.list]
List-initialization of an object or reference of type
T
is defined as follows:
—...
— Otherwise, ifT
is a reference type, a prvalue temporary of the type referenced byT
is list-initialized, and the reference is bound to that temporary
This, of course, means that the initialization of ar2
requires an accessible copy-constructor, hence the error.
The language has changed in N3797, where the initialization from an initializer list containing a single element takes precedence over the case quoted above.
— Otherwise, if the initializer list has a single element of type
E
and eitherT
is not a reference type or its referenced type is reference-related toE
, the object or reference is initialized from that element;...
— Otherwise, ifT
is a reference type, a prvalue temporary of the type referenced byT
is copy-list-initialized or direct-list-initialized, depending on the kind of initialization for the reference, and the reference is bound to that temporary.
So gcc 4.9 and clang 3.4 are implementing the resolution of issue 1288, while gcc 4.8 is following the wording in the C++11 standard.
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