简体   繁体   English

结构化绑定是否应该从 function 作为 C++20 中的右值返回?

[英]Shall structured binding be returned from a function as rvalue in C++20?

Consider a C++20 program where in function foo there is a structured binding auto [y] .考虑一个 C++20 程序,其中 function foo中有一个结构化绑定auto [y] The function returns y , which is converted in object of type A . function 返回y ,它在A类型的 object 中转换。 A can be constructed either from const reference of from rvalue-reference. A可以从 const 引用或右值引用构造。

#include <tuple>
#include <iostream>

struct A {
    A(const int &) { std::cout << "A(const int &) "; }
    A(int &&) { std::cout << "A(int &&) "; }
};

A foo() {
    auto [y] = std::make_tuple(1);
    return y;
}

int main() { foo(); }

Which one of the constructors shall be selected according to C++20 language standard?按照C++20语言标准,应该选择哪一个构造函数?

Clang selects A(const int &) and GCC selects A(int &&) , demo: https://gcc.godbolt.org/z/5q779vE6T Clang 选择A(const int &)和 GCC 选择A(int &&) ,演示: https://gcc.godbolt.org/z/5q779vE6T

Does one of the compilers not support yet the standard in that respect?是否其中一个编译器不支持这方面的标准?

I believe that Clang is correct.我相信 Clang 是正确的。

TL;DR: some lvalues can be implicitly moved, but a structured binding is not such a lvalue. TL;DR:一些左值可以隐式移动,但结构化绑定不是这样的左值。

  1. The name of a structured binding is an lvalue:结构化绑定的名称是一个左值:

[dcl.struct.bind]/1 : [dcl.struct.bind]/1 :

A structured binding declaration introduces the identifiers v 0 , v 1 , v 2 ,… of the identifier-list as names of structured bindings.结构化绑定声明引入了标识符列表的标识符v 0v 1v 2 ……作为结构化绑定的名称。

[dcl.struct.bind]/4 : [dcl.struct.bind]/4 :

Each v i is the name of an lvalue of type T i that refers to the object bound to r i ;每个v i是类型T i的左值的名称,它引用绑定到r i的 object; the referenced type is r i .引用的类型是r i

  1. An variable name (which is normally an lvalue) can be moved in a return statement if it names an implicitly movable entity :如果变量名称(通常是左值)命名为隐式可移动实体,则它可以在return语句中移动:

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.隐式可移动实体是自动存储持续时间的变量,它是非易失性 object 或对非易失性 object 类型的右值引用。 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 ([stmt.return]) 或co_return ([stmt.return.coroutine]) 语句中的表达式是一个(可能带括号的) id 表达式,它命名在主体或参数声明子句中声明的隐式可移动实体最里面的封闭 function 或lambda-expression ,或
  • [...] [...]
  1. As can be seen in the definition of implicitly movable entity, only objects and (rvalue) references can be implicitly moved.从隐式可移动实体的定义中可以看出,只有对象和(右值)引用可以被隐式移动。 But a structured binding is neither.但是结构化绑定两者都不是。

[basic.pre]/3 : [basic.pre]/3 :

An entity is a value, object, reference, [or] structured binding[...].一个实体是一个值,object,引用,[或]结构化绑定[...]。

So I believe that a structured binding cannot be implicitly moved.所以我认为不能隐式移动结构化绑定。

If y were an object or reference, then it would be implicitly movable in return y;如果y是 object 或引用,那么它在return y; . .


Edit: C++17 as written specified that structured bindings to tuple members are references.编辑:C++17 所写的指定元组成员的结构化绑定是引用。 This was corrected by CWG 2313 . CWG 2313对此进行了更正。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM