【问题标题】:std::is_same returns false when comparing std::tuple_element and decltype(std::get)比较 std::tuple_element 和 decltype(std::get) 时,std::is_same 返回 false
【发布时间】:2019-05-16 09:42:39
【问题描述】:

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

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

  • 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" );

【问题讨论】:

  • get 可能返回一个右值引用,将std::remove_reference_t 拍到它上面。
  • 我很糟糕,我感觉很糟糕。你是对的先生。

标签: c++ c++14 decltype


【解决方案1】:

std::get(std::tuple) 返回引用;这意味着在其上使用 decltype 您将获得一个引用类型。

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

对于这种情况,std::get&lt;I&gt;(Tuple{}) 的返回类型是一个右值引用,那么std::get&lt;I&gt;(Tuple{}) 是一个xvalue expression

函数调用或重载的运算符表达式,其返回类型为对对象的右值引用,如std::move(x)

那么decltype(std::get&lt;I&gt;(Tuple{}))将是T&amp;&amp;,即float&amp;&amp;;这与typename std::tuple_element&lt;I, Tuple&gt;::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 对象。 如果 type 是引用类型,则结果引用代表引用类型的 std::type_info 对象。

这意味着typeid(float&amp;&amp;) == typeid(float) 始终是true

【讨论】:

  • 我更喜欢在这种情况下使用std::decay,即使删除引用可能就足够了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多