Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang, returning std::unique_ptr with type conversion

Tags:

c++

clang

c++14

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
like image 909
Michał Walenciak Avatar asked Apr 20 '16 18:04

Michał Walenciak


1 Answers

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.

like image 155
Barry Avatar answered Nov 14 '22 05:11

Barry