【发布时间】:2015-01-19 02:42:25
【问题描述】:
Recently I've discovered 有时能够临时将右值转换为左值 对我有用。
我一直在使用以下工具:
#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);
}
当您必须使用需要左值的函数时,它很有用 争论,但你对那些特别的东西没有任何兴趣 值变成。当您对其他输出感兴趣时 与给定的特定参数无关的向量。
例如,这个:
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));
我想确定我是否在其中任何一个中调用 undefined-behavior,因为我没有看到任何内容,尽管可能有一些强制转换规则会使其非法(我忽略) .关于临时人员的生命周期,我没有看到任何问题,因为 AFAIK,rvalues live until the end of full-expression 并且函数的使用仅限于此。
关于reinterpret_cast 和xvalues 的标准最近发生了变化
这似乎是主题:
https://stackoverflow.com/a/26793404/1000282
编辑:
按照建议使用参考折叠的更好版本:
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }
【问题讨论】:
-
你很好。通过将 xvalues 转换为 lvalues 可以更容易搞砸的唯一事情是生命周期问题,而且你是对的,你的示例中没有危险,因为在创建它的语句之外没有引用临时文件。 (
reinterpret_cast-proposal 实际上并未涉及您的问题。) -
@Deduplicator 谢谢,我说的是右值而不是专门的 xvalue,因为这个问题还包括像
&lvalue(5)这样的表达式。顺便说一句,它工作正常。 -
顺便说一句:你为什么使用
std::remove_reference_t而不是引用折叠规则? -
传递纯右值有效,因为它被复制到一个临时值,该临时值通过 xvalue-reference 传递给您的函数,并且该临时值只会在完整表达式的末尾被销毁,就像其余部分一样.关于简洁的改进:返回值而不是
std::remove_reference_t<T> &T&。顺便说一句:我打电话给我的no_move,它对默认参数也很有用。 -
@pepper_chico:是的。顺便说一句:
static_cast也是多余的。
标签: c++ c++11 language-lawyer undefined-behavior c++14