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

bre*_*att 7 c++ decltype c++14

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

我认为有两种“简单”的方法可以在编译时获取元组的第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" );
Run Code Online (Sandbox Code Playgroud)

son*_*yao 7

std::get(std::tuple)返回参考;这意味着使用decltype它,您将获得引用类型。

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

在这种情况下,的返回类型std::get<I>(Tuple{})是rvalue-reference,然后std::get<I>(Tuple{})xvalue表达式

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

生活

关于为什么typeid给出相同的结果,

(强调我的)

1)引用std::type_info代表类型类型的对象。如果type是引用类型,则结果引用std::type_info表示引用类型的对象。

typeid(float&&) == typeid(float)就是永远true

  • 我喜欢在这种情况下使用`std :: decay`,即使删除引用可能就足够了 (2认同)