比较std :: tuple_element和decltype(std :: get)时std :: is_same返回false

时间:2019-05-16 09:42:39

标签: c++ c++14 decltype

我找不到类似的问题...

我认为有两种“简单”的方法可以在编译时获取元组的第I个元素的类型(如果我错了,请纠正我):

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

实际上,如果我们通过typeid(...).name()打印每个类型,则它们返回相同的值。

但是...当我比较这些条件时,std::is_same返回false:

live example

这是预期的吗?为什么?

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 个答案:

答案 0 :(得分:7)

std::get(std::tuple)返回引用;也就是说,在其上使用decltype,您将获得引用类型。

  

a)如果表达式的值类别为xvalue,则decltype产生   T&&;
  b)如果表达式的值类别为左值,则decltype产生   T&;
  c)如果表达式的值类别是prvalue,则为decltype   产生T

在这种情况下,返回类型std::get<I>(Tuple{})是右值引用,然后std::get<I>(Tuple{})xvalue expression

  

函数调用或重载的运算符表达式,其返回类型是对对象的右值引用,例如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