clang error with std::unique_ptr

2019-03-18 13:19发布

问题:

I have base object called IList. Then I have VectorList, that inherits IList.

then I have function like this:

std::unique_ptr<IList> factory(){
    auto vlist = std::make_unique<VectorList>();
    return vlist;
}

This compiles without problem under gcc, but clang gives following error:

test_file.cc:26:9: error: no viable conversion from 'unique_ptr<VectorList, default_delete<VectorList>>' to
      'unique_ptr<IList, default_delete<IList>>'
        return vlist;

How is proper way to handle this kind of errors?

回答1:

It appears (your version of) Clang is still following C++11 behaviour in this regard. In C++11, you had to use std::move in this case, because the type of vlist is different from the return type, and so the clause of "when returning an lvalue, try it as an rvalue first" did not apply.

In C++14, this restriction of "same types required" was lifted, and so in C++14, you shouldn't need the std::move in the return statement. But if you need your code to compile with your current toolchain, simply add it there:

return std::move(vlist);

The exact C++11 wording was this:

12.8/32 When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. ...

The criteria for copy elision (which include "same type") have to be met; they're just slightly extended to cover parameters as well.

In C++14 (N4140), the wording is broader:

12.8/32 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.

(Emphasis mine)

As you can see, copy elision criteria are no longer required for the return case.