多个返回值(结构化绑定)与不可移动类型或保证RVO在C + + 17 [英] Multiple return values (structured bindings) with unmovable types or guaranteed RVO in C++17

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

问题描述

使用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具体不包括在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 实现对返回值 get_ensured_rvo_str ,因此 rvoStr 实际上是从实现临时的第一成员移动构造的,但是在这之前你有一个问题) / p>

(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.

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

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