构造助手make_XYZ允许RVO和类型推演,即使XZY具有非复制约束 [英] construction helper make_XYZ allowing RVO and type deduction even if XZY has noncopy constraint

查看:100
本文介绍了构造助手make_XYZ允许RVO和类型推演,即使XZY具有非复制约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

UPDATE1: C ++ 17为构造函数添加了类型推导-并不意味着free函数是劣等的解决方案。

UPDATE1: C++17 added type deduction for constructors - which does not imply that the free function is an inferior solution.

UPDATE2: C ++ 17添加了保证的复制保留(复制从概念上讲甚至没有发生)。因此,对于C ++ 17,我的代码实际上可以正常工作并具有最佳性能。但是,我相信Martinho使用括号初始化返回值的代码仍然是更干净的解决方案。但是结帐巴里的答案和TC的评论

UPDATE2: C++17 added guaranteed copy elision (the copy does not even take place conceptually). So with C++17 my code actually works and with optimal performance. But Martinho's code using brace initialisation for the return value is still the cleaner solution I believe. But checkout this answer from Barry and the comment from T.C.

OLD POST :类型推导不适用于构造函数(至少直​​到C ++ 11包括)。常见的解决方案是依靠RVO(返回值优化)并编写一个make_XYZ模板函数,将其参数转发给构造函数。一个示例是 std :: make_tuple

OLD POST: Type deduction does not work for constructors (at least until and including C++11). The common solution is to rely on RVO (Return Value Optimisation) and write a make_XYZ template function that forwards its parameters to the constructor. An example is std::make_tuple.

任何模板杂技演员都知道无复制策略时可以解决此问题的解决方法在路上?有效的解决方案仍必须允许RVO发生。

Any template acrobat who knows a workaround to make this work when nocopy policy is in the way? A valid solution must still allow RVO to happen.

此外,对于任何make_XYZ的要求都会在C ++ 14中消失吗?

Additionally, will the requirement for any make_XYZ disappear with C++14?

#include <iostream>

template <typename T>
struct XYZ
{
    // remove following two lines to make the code compile
    XYZ (XYZ const & rhs) = delete; 
    XYZ (XYZ && rhs) = delete; 
    T i;
    XYZ (T i):i(i)
    {
    }
};

template <typename T>
XYZ<T> make_XYZ (T && i)
{
    return XYZ<T>(std::forward<T>(i));
}

int main ()
{
    auto x = make_XYZ(1);
    std::cout << x.i << std::endl;
}


推荐答案

如果存在非显式构造函数,确实有可能通过值返回不可复制和不可移动的类型。查看实时示例: http://coliru.stacked-crooked.com/a/89ef9d3115924558

If there is a non-explicit constructor, it is indeed possible to return a non-copiable and non-movable type by value. See live example: http://coliru.stacked-crooked.com/a/89ef9d3115924558.

template <typename T>
XYZ<T> make_XYZ (T && i)
{
    return { std::forward<T>(i) };
}

这里的棘手之处在于 {... } 不会构造一个临时并将其移至返回值。它是直接初始化返回值。没有复制也没有移动,这与是否应用任何优化无关(如果需要优化才能工作,它将不会编译)。

The tricky bit here is that { ... } is not constructing a temporary and moving it to the return value. It is directly initialising the return value. There is no copy nor move, and that is irrelevant of whether any optimisation applies (it wouldn't compile if it required an optimisation to work).

但是,由于类型是不可复制或不可移动的,因此您将无法按值将其存储在局部变量中。但是,您可以使用旧的临时生命周期扩展技巧来保存它:

However, since the type is not copyable nor movable, you will not be able to store it in a local variable by value. You can, however, use the old temporary lifetime extension trick to hold it:

auto&& x = make_XYZ(1);

这篇关于构造助手make_XYZ允许RVO和类型推演,即使XZY具有非复制约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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