clang,返回带有类型转换的std::unique_ptr

clang, returning std::unique_ptr with type conversion

本文关键字:std unique ptr 类型转换 返回 clang      更新时间:2023-10-16

这是我的代码:

#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;
}

它没有在clang上编译错误:

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>>'

然而,根据这个(同样的情况)它应该。我误解什么了吗?

我的命令行(clang ver 3.7):

clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

这是一个clang bug。来自[class.copy]:

当满足省略复制/移动操作的条件,但不满足异常声明的条件时,并且当return语句中的表达式为(可能带括号)id表达式,用于命名在正文或最里面的封闭函数或lambda表达式的参数声明子句,重载解析为副本选择构造函数首先执行,就好像对象是由rvalue指定的一样

省略的条件没有得到满足(因为p的类型与函数的返回类型不同),但代码应该仍然有效,因为重载解析应该像p是右值一样进行。

也就是说,你确实希望移动省略发生,所以在这种情况下不要使用auto

std::unique_ptr<A> test() 
{
    std::unique_ptr<A> p = std::unique_ptr<B>();
    return p;
}

clang接受此代码,并且移动省略将发生。双赢。

您需要从unique_ptr中move。以下代码在CLang和gcc上编译:

#include <memory>
struct A{};
struct B: A {};
std::unique_ptr<A> test() 
{
    auto p = std::make_unique<B>();
    return std::move(p);
}