返回 pair/struct/tuple 时参数的顺序在以下代码中是否重要?

Does the order of arguments while returning a pair/struct/tuple matter in following code?

在以下代码中,是否正确创建了 return 值。我有一些疑问,因为 pair 构造函数的两个参数都是相关的。对第二个参数使用 move 是否会破坏第一个参数。或者如果第一个参数总是在第二个参数之前创建:

class A
{
    private:
        struct B
        {
            int a;
            string b;
            int c;
        };

        struct C
        {
            double d;
            float f;
        };

        struct Key
        {
            int a;
            string b;
            double d;
        };
        
        struct Data
        {
            B x;
            C y;
        };
        
    public:
        Data data;
        
        using ReturnType = pair<Key, Data>;        
        ReturnType operator()(Source input)
        {
            // use input to fill Data
            
            return {{data.x.a, data.x.b, data.y.d}, move(this->data)};
        }    
};

注意:来源可能是数据库游标、标准输入流,也可能是包含相关数据的文件指针。

C++ 标准是否定义了创建对的顺序。 c++11和c++17在这方面有什么区别吗?

来自this evaluation order reference

  1. In list-initialization, every value computation and side effect of a given initializer clause is sequenced before every value computation and side effect associated with any initializer clause that follows it in the brace-enclosed comma-separated list of initalizers.

表达的意思是

{{data.x.a, data.x.b, data.y.d}, move(this->data)}

{data.x.a, data.x.b, data.y.d} 部分将在之前排序(即在之前评估)move(this->data)

n3337,C++11标准草案,包含这段话

[dcl.init.list]

4 Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions ([temp.variadic]), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. — end note ]

因此,当使用大括号初始化时,初始化 ReturnType 中的 Key 的参数将在 Data 的参数之前被完整计算。

此后每个 C++ 标准中都有类似的措辞。