C ++ 17中具有不可移动类型和保证的RVO的多个返回值(结构化绑定) [英] Multiple return values (structured bindings) with unmovable types and guaranteed RVO in C++17

查看:175
本文介绍了C ++ 17中具有不可移动类型和保证的RVO的多个返回值(结构化绑定)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于C ++ 17,我们将有可能返回可以移动的(包括不可复制的)类型,例如 std :: mutex ,这可以被认为是保证的返回值。优化(RVO):通过简化的值保证了复制省略类别

With C++ 17, we will have the possibility to return unmovable (including uncopyable) types such as std::mutex, via what can be thought of as guaranteed return value optimization (RVO): Guaranteed copy elision through simplified value categories:

struct nocopy { nocopy(nocopy&) = delete; nocopy() = default; };
auto getRVO(){
    return nocopy();
}

我们还将有结构化绑定,允许:

tuple<T1,T2,T3> f();
auto [x,y,z] = f();

或(在这里也使用我对功能构造函数的模板参数推导

or (here also using my understanding of the feature template argument deduction for constructors)

template<typename T1,typename T2,typename T3>
struct many {
  T1 a;
  T2 b;
  T3 c;
};
// (Original questions missed 'many' on the next line. Thanks, T.C.)
auto f(){ return many{string(),5.7, false} }; 
auto [x,y,z] = f();

但是,这些功能是否组成了这样的功能?

But do these features compose to enable something like this?

auto get_ensured_rvo_str(){
    return std::pair(std::string(),nocopy());
}

auto get_class_and_mutex(){
    return many{SomeClass(),std::mutex(),std::string()};
}

int main(){
    auto rvoStr = get_ensured_rvo_str().first;
    auto [ mtx,sc,str ] = get_class_and_mutex();
}

我的想法是,要使其正常工作,就需要保证在构造 std :: tuple 很多时聚集构造函数参数,但不会将其命名为RVO(NRVO) P0144R2提议中具体不包括?

My thinking is that for this to work, it would required guaranteed RVO of the aggregate constructor arguments at forming std::tuple or many, but wouldn't that be named RVO (NRVO) which is specifically not included in the P0144R2 proposal?

侧面说明:P0144R2特别提到支持仅移动类型:

Side note: P0144R2 specifically mentions that move-only types are supported:


2.6仅移动类型



仅移动类型受支持。例如:

2.6 Move-only types

Move-only types are supported. For example:

struct S { int i; unique_ptr<widget> w; };
S f() { return {0, make_unique<widget>()}; }
auto [ my_i, my_w ] = f();



推荐答案


template<typename T1,typename T2,typename T3>
struct many {
  T1 a;
  T2 b;
  T3 c;
};
auto f(){ return {string(),5.7, false} };


这不会编译。首先,您从未说过 f 是要返回很多的方法。其次,类模板参数推导可与构造函数一起使用,许多的唯一构造函数是隐式声明的默认,复制和移动构造函数。

This won't compile. First you never said f is to return a many. Second, class template argument deduction work with constructors, and the only constructors of many are the implicitly declared default, copy and move constructors.

您需要一个指南:

template<class T1, class T2, class T3>
many(T1, T2, T3) -> many<T1, T2, T3>;




auto get_ensured_rvo_str(){
    return std::pair(std::string(),nocopy());
}


这也不起作用。 nocopy()被实现为一个临时对象,该临时对象绑定到 pair 的构造函数的参考参数,然后尝试从它移动并失败。

This doesn't work either. nocopy() is materialized into a temporary that is bound to the reference parameter of pair's constructor, which then attempts to move from it and fails. No elision of that temporary is possible or allowed.

(当然,正如Nicol Bolas在他的答案中指出的那样, get_ensured_rvo_str中的类成员访问权限().first 实现 pair 返回值 get_ensured_rvo_str ,因此<$ c $实际上,c> rvoStr 是从该物化临时对象的 first 成员构造的。但是在此之前,您有一个问题。)

(Of course, as Nicol Bolas points out in his answer, the class member access in get_ensured_rvo_str().first materializes the pair return value of get_ensured_rvo_str, so rvoStr would in fact be moved constructed from the first member of that materialized temporary. But here you have a problem well before that.)


auto get_class_and_mutex(){
    return many{SomeClass(),std::mutex(),std::string()};
}
auto [ mtx,sc,str ] = get_class_and_mutex();


这很好(假设您有一个推论指南)。聚集初始化不会调用很多的任何构造函数;直接使用相应的prvalue初始化程序初始化成员。

This is fine (assuming you have a deduction guide). Aggregate initialization doesn't call any constructor of many; it initializes the members directly with the corresponding prvalue initializer.

这篇关于C ++ 17中具有不可移动类型和保证的RVO的多个返回值(结构化绑定)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆