pep*_*ico 14 c++ undefined-behavior language-lawyer c++11 c++14
最近我发现 ,有时能够将rvalues 暂时变成左值对我来说很有用.
我一直在使用以下工具:
#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);
}
Run Code Online (Sandbox Code Playgroud)
当您必须使用需要左值作为参数的函数时,它很有用,但您对这些特定值的变化没有任何兴趣.当您对与给定的特定参数无关的其他输出向量感兴趣时.
例如,这个:
std::string get_my_file() {
std::ifstream ifs("myfile.txt");
return {std::istreambuf_iterator<char>(ifs), {}};
}
Run Code Online (Sandbox Code Playgroud)
可以改为:
std::string get_my_file() {
return {std::istreambuf_iterator<char>(lvalue(std::ifstream("myfile.txt"))),
{}};
}
Run Code Online (Sandbox Code Playgroud)
还有这个:
std::string temp1 = get_my_shader();
const char *temp2 = temp1.c_str();
glShaderSource(a, 1, &temp2, nullptr);
Run Code Online (Sandbox Code Playgroud)
可以改为:
glShaderSource(a, 1, &lvalue(get_my_shader().c_str()), nullptr);
Run Code Online (Sandbox Code Playgroud)
并允许这样的事情:
void foo(int *x) {
std::cout << *x << std::endl;
}
foo(&lvalue(5));
Run Code Online (Sandbox Code Playgroud)
我想确定我是否在调用任何未定义的行为,因为我没有看到任何行为,尽管可能会有一些转换规则将其视为非法(我忽略).关于临时的生命,我没有看到问题,因为AFAIK,rvalues直到完全表达结束并且函数的使用仅限于此.
有一个最近约标准的变化reinterpret_cast
和xvalues
这似乎是在题目:
编辑:
更好的版本使用参考折叠建议:
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }
Run Code Online (Sandbox Code Playgroud)
正如你所说,你注意不要让任何指针或对临时工具的引用逃脱它们的范围.
使用你的lvalue
函数(我的函数被调用no_move
)可以更容易地在不经意间打破这种限制.
接下来,让我们看看是什么xvalues
:过期对象,但对象.
这意味着,你可以忽略他们正在参加他们的葬礼之旅(如果你把它们传递给一个函数,那个函数自然会这样做,除非你要求利用).
你提到的最后一点是使用prvalue调用,这肯定不是一个对象.
但即使这不是问题,因为在调用函数时,会创建一个临时函数.
而那个临时性自然也会存在到声明的最后.
另外,std::remove_reference_t<T>&
对于返回类型,使用是不必要的lvalue
,您可以T&
直接使用并依赖于引用 - 折叠规则.此外,static_cast
和inline
是多余的.
template <typename T> constexpr T& lvalue(T&& r) noexcept {return r;}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
536 次 |
最近记录: |