I apologize if the question title is inaccurate - but I am having difficulties understanding what is going on here.
Consider the following class:
struct foo {
foo(foo&);
};
The following has no errors:
void func(foo& f) {
foo bar{f};
}
However, when I use auto:
void func(foo& f) {
auto bar = foo{f};
}
I get (gcc):
test.cpp: In function ‘void func(foo&)’:
test.cpp:6:21: error: no matching function for call to ‘foo::foo(foo)’
test.cpp:6:21: note: candidate is:
test.cpp:2:5: note: foo::foo(foo&)
test.cpp:2:5: note: no known conversion for argument 1 from ‘foo’ to ‘foo&’
(clang)
test.cpp:6:10: error: no matching constructor for initialization of 'bar'
auto bar = foo{f};
^ ~~~~~~
test.cpp:2:5: note: candidate constructor not viable: expects an l-value for 1st argument
foo(foo&);
^
Can somebody please explain why this is an error?
Thanks!
Edit: It works if I add a copy-constructor to foo. However, I was under the impression that the variable declaration + explicit call to constructor on the right side of the '=' syntax is treated specially and is not a copy-construction but rather a direct initialization.
auto bar = foo{f};
auto
is deduced as foo
. Subsequently, your definition is equivalent to
foo bar = foo{f};
You are trying to create an object of type foo
that is copy-initialized with the prvalue foo{f}
.
The problem is that the copy constructor of foo
has a non-const lvalue reference as its parameter, which is impossible to bind to an rvalue. Also, the move constructor isn't implicitly defined as you have a user-declared copy constructor. Hence there is no constructor that can take foo{f}
, and the compiler issues an error message.
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