将xvalues强制转换为lvalues以传递给函数是否定义明确? [英] Is it well-defined to cast xvalues to lvalues for passing to functions?

查看:86
本文介绍了将xvalues强制转换为lvalues以传递给函数是否定义明确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我发现了 有时能够将右值临时转换为左值可以是 对我有用.

Recently I've discovered that sometimes being able to turn rvalues temporarily into lvalues can be useful for me.

我一直在使用以下工具:

I've been using the following tool:

#include <type_traits>

template <typename T>
inline constexpr std::remove_reference_t<T> &lvalue(T &&r) noexcept {
    return static_cast<std::remove_reference_t<T> &>(r);
}

当您必须使用需要左值的函数时非常有用 论点,但您对这些特殊之处不感兴趣 值变成.当您对其他输出感兴趣时 与给定特定参数无关的向量.

It's useful when you have to use functions that require lvalues as arguments, but you don't have any interest in what those particular values get changed into. For when you are interested in other output vectors that are not related to the given specific argument.

例如,此:

std::string get_my_file() {
    std::ifstream ifs("myfile.txt");
    return {std::istreambuf_iterator<char>(ifs), {}};
}

可以更改为此:

std::string get_my_file() {
    return {std::istreambuf_iterator<char>(lvalue(std::ifstream("myfile.txt"))),
            {}};
}

这:

std::string temp1 = get_my_shader();
const char *temp2 = temp1.c_str();
glShaderSource(a, 1, &temp2, nullptr);

可以更改为此:

glShaderSource(a, 1, &lvalue(get_my_shader().c_str()), nullptr);

并允许这样的事情:

void foo(int *x) {
    std::cout << *x << std::endl;
}

foo(&lvalue(5));

我想确定是否以任何方式调用未定义行为,因为我看不到任何行为,尽管可能存在某些强制转换规则,但该规则将其视为非法(我忽略了) .关于临时对象的生命周期,我没有看到任何问题,因为AFAIK, rvalues有效期到完全表达式结束,并且该功能的使用仅限于此.

I'd like to be sure whether I'm invoking undefined-behavior or not in any of this, because I don't see any, although there may be some casting rule that would turn it illegal (which I ignore). Regarding lifetime of temporaries, I don't see a problem since, AFAIK, rvalues live until the end of full-expression and usage of the function is restricted to that.

关于reinterpret_castxvalues的标准最近进行了更改 似乎是关于主题:

There's a recent change to the standard about reinterpret_cast and xvalues that seems to be on topic:

https://stackoverflow.com/a/26793404/1000282

编辑:

建议使用参考折叠的更好版本:

Better version using reference collapsing as suggested:

template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }

推荐答案

正如您所说,请注意不要让任何指向临时对象的指针或引用转义其范围.
使用您的lvalue函数(我的被称为no_move)可以更容易地无意间破坏该约束.

As you said, you took care to not let any pointer or reference to the temporaries escape their scope.
Using your lvalue-function (mine is called no_move) makes it easier to break that stricture inadvertently.

接下来,让我们看一下xvalues是什么:过期的对象,但是对象仍然存在.
这意味着,您可以忽略他们的葬礼之旅(如果将它们传递给某个函数,除非您要求利用,否则该函数自然会这样做).

Next, let's look at what xvalues are: Expiring objects, but objects nevertheless.
This means, you can ignore they are on their funeral tour (if you pass them to a function, that function will naturally do so, unless you ask to take advantage).

您提到的最后一点是使用prvalue进行调用,这当然不是对象.
但这不是问题,因为在调用函数时会创建一个临时目录.
而且这种临时性自然也可以保留到声明的结尾.

The last point you mentioned was calling with a prvalue, which is most certainly not an object.
But even that is not a problem, as on calling the function, a temporary will be created.
And that temporary will naturally also survive to the end of the statement.

顺便说一句,对于lvalue的返回类型,不必使用std::remove_reference_t<T>&,您可以直接使用T&并依赖于reference-collapsing-rules.另外,static_castinline是多余的.

As an aside, using std::remove_reference_t<T>& is unneccessary for the return-type of lvalue, you can use T& directly and rely on the reference-collapsing-rules. Also, the static_cast and inline are superfluous.

template <typename T> constexpr T& lvalue(T&& r) noexcept {return r;}

这篇关于将xvalues强制转换为lvalues以传递给函数是否定义明确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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