#c
#c
Вопрос:
Я хочу разработать функцию разыменования для необязательных
Когда я даю ссылку lvalue на функцию, я хочу, чтобы возвращаемый тип был ссылкой на значение lvalue. (т. е. intamp;
)
Когда я передаю временный объект (т. Е. prvalue) функции, я хочу, чтобы возвращаемый тип был устаревшим типом (т. Е. int
)
Когда я передаю функции перемещенный объект (т. Е. xvalue), я хочу, чтобы возвращаемый тип был ссылкой на значение rvalue (т. е. intamp;amp;
)
Я написал 2 функции :
template<typename T>
decltype(auto) bad(T amp;amp;t) {
return *fwd(t);
}
Эта функция возвращает ссылку на значение rvalue, когда мы даем значение prvalue, и, таким образом, мы получаем висячую ссылку
struct remove_rvalue_reference {
using type = std::decay_t<T>;
};
template <typename T>
struct remove_rvalue_reference<T amp;> {
using type = T amp;;
};
template <typename T>
using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;
template<typename T>
auto good(T amp;amp;t) -> remove_rvalue_reference_t<decltype(*fwd(t))> {
return *fwd(t);
}
Эта функция работает хорошо, но когда мы задаем значение x, мы получаем устаревший тип, но нам нужна ссылка на значение rvalue
Вот пример кода
#include <optional>
#include <iostream>
#include <type_traits>
#define fwd(x) ::std::forward<decltype(x)>(x)
template <typename T>
struct remove_rvalue_reference {
using type = std::decay_t<T>;
};
template <typename T>
struct remove_rvalue_reference<T amp;> {
using type = T amp;;
};
template <typename T>
using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;
template<typename T>
decltype(auto) bad(T amp;amp;t) {
return *fwd(t);
}
template<typename T>
auto good(T amp;amp;t) -> remove_rvalue_reference_t<decltype(*fwd(t))> {
return *fwd(t);
}
int main() {
std::optional<int> a = 5;
// both are lvalue reference
decltype(auto) aref = bad(a); // ok
decltype(auto) aref2 = good(a); // ok
static_assert(std::is_lvalue_reference_v<decltype(aref)>);
static_assert(std::is_lvalue_reference_v<decltype(aref2)>);
decltype(auto) arvref = bad(std::move(a)); // ok
decltype(auto) arvref2 = good(std::move(a)); // not ok : not a rvalue reference -> lose perf
static_assert(std::is_rvalue_reference_v<decltype(arvref)>);
static_assert(!std::is_reference_v<decltype(arvref2)>);
decltype(auto) rvref = bad(std::make_optional(5)); // NOT OK !! DANGLING REF
decltype(auto) rvref2 = good(std::make_optional(5)); // OK
static_assert(std::is_rvalue_reference_v<decltype(rvref)>);
static_assert(!std::is_reference_v<decltype(rvref2)>);
}
Комментарии:
1. Я не думаю, что есть способ отличить prvalues от аргументов xvalue.
2. Это то, чего я боюсь…