Here is my code:
#include <memory>
struct A{};
struct B: A {};
std::unique_ptr<A> test()
{
auto p = std::make_unique<B>();
return p;
}
int main(int argc, char **argv)
{
test();
return 0;
}
It doesn't compile on clang with error:
main.cpp:11:12: error: no viable conversion from returned value of type 'unique_ptr<B, default_delete<B>>' to function return type 'unique_ptr<A, default_delete<A>>'
However, according to this (same situation) it should. Did I misunderstand something?
My command line (clang ver 3.7):
clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
This is a clang bug. From [class.copy]:
When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a
return
statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
The criteria for elision aren't met (because p
doesn't have the same type as the return type of the function), but the code should still be valid since overload resolution should be done as if p
were an rvalue.
That said, you do want move elision to happen, so prefer to not use auto
in this case:
std::unique_ptr<A> test()
{
std::unique_ptr<A> p = std::unique_ptr<B>();
return p;
}
clang accepts this code and move elision will happen. Win win.
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