Недавно я обнаружил что иногда возможность временного превращения rvalues в lvalues может быть полезно для меня.
Я использовал следующий инструмент:
#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);
}
Это полезно, когда вам нужно использовать функции, которые требуют lvalues как аргументы, но у вас нет интереса к тому, что значения меняются. Если вас интересует другой выход векторы, которые не связаны с заданным конкретным аргументом.
Например, это:
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 живут до конца полного выражения, и использование функции ограничено этим.
Недавнее изменение стандарта о reinterpret_cast
и xvalues
это похоже на тему:
ИЗМЕНИТЬ
Лучшая версия, использующая обращение с рекомендациями:
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }