Хорошо ли определено приводить xvalues к lvalues для передачи в функции?
Недавно я обнаружил что иногда возможность превратить ценностивременно в 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));
Я хотел бы быть уверен, что я вызываю неопределенное поведение или нет в любом из этого, потому что я не вижу ничего, хотя может быть какое-то правило приведения, которое сделает его незаконным (что я игнорирую). Что касается времени жизни временных, я не вижу проблем с тех пор, AFAIK,rvalues живут до конца полного выражения и использование функции ограничено этим.
Есть недавнее изменение в стандарте оreinterpret_cast
а такжеxvalues
похоже на тему:
https://stackoverflow.com/a/26793404/1000282
РЕДАКТИРОВАТЬ:
Лучшая версия с использованием свертывания ссылок, как предложено:
template <typename T>
constexpr T &lvalue(T &&r) noexcept { return r; }