【问题标题】:C++ implicit conversion and universal forwarding on gcc 7.5gcc 7.5 上的 C++ 隐式转换和通用转发
【发布时间】:2021-02-08 09:32:08
【问题描述】:

我正在创建一个使用通用转发的库组件。 这在大多数情况下都可以正常工作,但我遇到过我们的 linux 构建(看似)错误地使用复制构造函数而不是移动构造函数的情况。

我能够使用 MVE 在 gcc 7.5(与我们的 linux 构建平台相同)上的 godbolt 中重现此内容:

#include <iostream>
using namespace std;

struct A 
{
    A(){}
    A(const A&) = delete;
    A(A&& other){ cout << "move A " << endl; }
};

template<class T>
struct B
{
    template<class U = T>
    B(U&& other)
    : m_a(std::forward<U>(other))
    {
        cout << "forward T into B " << endl;
    }
    T m_a;
};

B<A> foo(A a)
{
    return a;
    //return std::move(a);
}

int main() 
{    
    A a;
    auto b = foo(std::move(a));
}

为了清楚起见,我添加了不可编译的版本来说明问题。

现在,据我所知,在这种情况下我不能使用 (N)RVO,因此移动本身并不是错误的,但我宁愿避免编写 return move(...); 当使用 gcc 8.1(或相对较新的 MSVC)编译它时,它确实使用了没有移动的移动构造函数。那么这只是一个编译器问题还是我需要改进我的“B”结构来处理这种情况?

【问题讨论】:

  • 该示例应该重现什么问题?链接的godbolt编译没有错误。
  • 链接的godbolt有编译返回std::move(a);我现在添加了非编译返回 a;希望这更清楚。
  • 我建议相应地更改问题中的代码。
  • 好的,完成。希望这能更清楚地说明问题。简而言之,我想在我的回归中避免搬家。
  • 这是core issue 1579,它是fixed for gcc 8

标签: c++ c++17 gcc4


【解决方案1】:

显示的程序(使用return a;)自 C++17 以来格式良好。因此,您需要一个符合 C++17 的编译器来编译它。 GCC 7 中的 C++17 支持是实验性的(C++17 尚未发布)。

使用 return std::move(a); 自 C++11 以来格式正确,应该适用于更老的编译器。


关于使其在 C++17 中工作的不同措辞:

C++14(草案):

[class.copy]

当满足省略复制/移动操作的条件时,但不用于异常声明,并且要复制的对象由左值指定,或者当return 语句是一个(可能带括号的)id 表达式,它命名一个具有自动存储持续时间的对象,该对象在 t (3.1) 的主体或参数声明子句中声明 在最内层的封闭函数或 lambda 表达式中,首先执行为复制选择构造函数的重载决策,就好像对象是由右值指定的一样。

当满足某些条件时,允许实现省略类对象的复制/移动构造...

  • 在具有类返回类型的函数的 return 语句中,当表达式是非易失性自动对象的名称(函数以外或catch子句参数)

C++17(草案):

[class.copy.elision]

隐式可移动实体是一个具有自动存储持续时间的变量,它可以是非易失性对象,也可以是对非易失性对象类型的右值引用。在以下复制初始化上下文中,在尝试复制操作之前首先考虑移动操作:

  • 如果 return ([stmt.return]) 或 co_return ([stmt.return.coroutine]) 语句中的表达式是一个(可能带括号的)id 表达式,它命名在主体或参数中声明的隐式可移动实体 -最内层封闭函数或 lambda 表达式的声明子句,或

简而言之,return 语句中的自动移动而不是从左值复制规则曾经与不适用于函数参数的复制/移动省略规则相结合。现在,它们已经解耦,前者也显式应用于函数参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多