gpt4 book ai didi

gcc 7.5 上的 C++ 隐式转换和通用转发

转载 作者:行者123 更新时间:2023-12-04 08:08:29 27 4
gpt4 key购买 nike

我正在创建一个使用通用转发的库组件。
这在大多数情况下都可以正常工作,但我遇到过我们的 linux 构建(似乎)错误地使用复制构造函数而不是移动构造函数的情况。
我能够在 godbolt 中重现这个在带有 MVE 的 gcc 7.5(与我们的 linux 构建平台相同)上:

#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”结构来处理这种情况?

最佳答案

所示程序(使用 return a; )自 C++17 起格式良好。因此,您需要一个符合 C++17 的编译器来编译它。 GCC 7 中的 C++17 支持是实验性的(C++17 尚未发布)。
使用 return std::move(a);自 C++11 以来格式良好,因此应该适用于更旧的编译器。

关于使其在 C++17 中工作的不同措辞:
C++14(草案):

[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 t (3.1)he 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.

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object ...

  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter)

C++17(草案):

[class.copy.elision]

An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following copy-initialization contexts, a move operation is first considered before attempting a copy operation:

  • If the expression in a return ([stmt.return]) or co_­return ([stmt.return.coroutine]) statement is a (possibly parenthesized) id-expression that names an implicitly movable entity declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or

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

关于gcc 7.5 上的 C++ 隐式转换和通用转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66098992/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com