std::get(std::tuple)
возвращает ссылку;это означает, что, используя decltype
, вы получите ссылочный тип.
a) если категория значений выражения xvalue, тогда decltype дает T&&
;
b) если категория значения выражения lvalue, тогда decltype возвращает T&
;
c) если категория значения выражения prvalue, тогда decltype дает T
.
В этом случае тип возврата std::get<I>(Tuple{})
является ссылкой-значением, тогда std::get<I>(Tuple{})
является выражением значения x ,
вызовом функции или перегруженным выражением оператора,тип возвращаемого значения - rvalue ссылка на объект, например std::move(x)
;
, тогда decltype(std::get<I>(Tuple{}))
будет T&&
, то есть float&&
;что отличается от typename std::tuple_element<I, Tuple>::type
(то есть float
).
Используя std::remove_reference
, вы можете получить то, что вы хотите.Например,
static_assert(std::is_same<typename std::tuple_element<I, Tuple>::type,
std::remove_reference_t<decltype(std::get<I>(Tuple{}))>>::value, "different types" );
LIVE
И о том, почему typeid
дает такой же результат,
(выделено мной)
1) Относится к объекту std::type_info
, представляющему тип. Если тип является ссылочным типом, результат относится к объекту std::type_info
, представляющему ссылочный тип.
Это означает, что typeid(float&&) == typeid(float)
всегда true
.