std :: is_same возвращает false при сравнении std :: tuple_element и decltype (std :: get) - PullRequest
7 голосов
/ 16 мая 2019

Не могу найти похожий вопрос ...

Я думаю, что есть два "простых" способа получить тип I-го элемента кортежа во время компиляции (поправьте меня, если я ошибаюсь):

  • using TI1 = typename std::tuple_element<I, Tuple>::type;
  • using TI2 = decltype(std::get<I>(Tuple{}));

Фактически, если мы печатаем типы каждого из них через typeid(...).name(), они возвращают одно и то же значение.

Однако ... std::is_same возвращает false при сравнении:

живой пример

Ожидается ли это? Зачем?

using Tuple = std::tuple<float,double>;
constexpr size_t I = 0;
static_assert(std::is_same<typename std::tuple_element<I, Tuple>::type,
                           decltype(std::get<I>(Tuple{}))>::value, "different types" );

1 Ответ

7 голосов
/ 16 мая 2019

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...