【问题标题】:clang, returning std::unique_ptr with type conversionclang,返回带有类型转换的 std::unique_ptr
【发布时间】:2016-04-20 18:53:36
【问题描述】:

这是我的代码:

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

但是,根据this(相同的情况)它应该。 我是不是误会了什么?

我的命令行(clang 版本 3.7):

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

【问题讨论】:

  • 在 gcc 5.3.0 coliru.stacked-crooked.com/a/73b3835e4eafbc7d 上编译。顺便说一句,您的 A 没有虚拟析构函数。
  • 这是同一个问题。 gcc 接受它。
  • 看来 clang 还没有解决这个问题。它仍然无法在 clang 3.8.0 上编译
  • @milleniumbug:关于析构函数,你是 100% 正确的,但它只是说明问题的快速草稿。

标签: c++ clang c++14


【解决方案1】:

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

当满足省略复制/移动操作的条件时,但不满足异常声明,并且 当return 语句中的表达式为(可能 带括号的)id-expression,它命名一个具有在正文中声明的自动存储持续时间的对象或 parameter-declaration-clause 最里面的封闭函数或 lambda-expression,重载决议 首先执行为副本选择构造函数就好像对象是由右值指定的

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

也就是说,您确实希望发生移动省略,因此在这种情况下最好不要使用auto

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

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

【讨论】:

  • 有趣的是 gcc 仍然存在反向错误 - 它允许此代码在 c++11 模式下:D
  • @SergeyA:在链接问题的评论中,有解释:“这是针对 C++11 的 DR,因此具有追溯性。请参阅 CWG 1579
  • @Jarod42,哦!我不知道!感谢您的澄清。
  • 什么是“真正的” DR-to-be-applied-retroactively 不是“官方”的东西,我相信。官方只是标准的文本,gcc 不会严格遵守。将某些 DR 解决方案追溯应用到“外观有缺陷”的 DR 通常被认为不会改变一致性。但据我所知,这些特定的 DR 并没有写在任何官方的地方。
【解决方案2】:

您需要来自 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);
}

【讨论】:

  • @RafałRawicki,因为它是 CLang 中的一个错误,在 C++11 模式下仍然存在。
  • 这是对 c++11 的修复,但代码在 c++14 中应该是有效的。这是一个有效的解决方法。
猜你喜欢
  • 1970-01-01
  • 2022-01-12
  • 2021-09-23
  • 2015-12-20
  • 2013-06-29
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多