decltype(std::get<0>(tup)) 究竟是什么?

What exactly is decltype(std::get<0>(tup))?

我目前正在学习 C++ 元编程,我正在尝试查看元组的元素是否是指针。我试过这种方法:

int a = 3, b = 4;
auto tup = std::make_tuple(&a, b);
std::cout << std::is_pointer<decltype(std::get<0>(tup))>::value; //prints 0

我觉得这很奇怪,所以我检查了推导的 clang 类型(我使用的是 clang-10),它是

__tuple_element_t<0UL, tuple<int *, int>

它看起来像某种内部类型。

为什么我会得到这种奇怪的类型,什么是获取元组元素实际类型的正确方法?我只有一个使用中间 auto 变量的解决方案,但几乎不是最优的。

std::is_same/std::is_same_v 在 TMP 中非常有用,在寻找与其他类型相等的类型时,与 static_assert.[=44 结合使用时非常有用=]

通过以下代码,您可以看到 std::get 为您提供了对元组元素的引用(由 cppreference's page on std::get 确认),在本例中为 int*&,其中 int* 是元素的类型。如果你用它来初始化 另一个 变量,你会得到它的一个副本(所以不再参考 elem,只是 int*),就像 int x = r;x 定义为 r 的副本,而不管 r 是否为引用。

#include <type_traits>
#include <tuple>

int main() {
    int a = 3, b = 4;
    auto tup = std::make_tuple(&a, b);
    auto elem = std::get<0>(tup);
    static_assert(std::is_same_v<decltype(elem), int*>,"");
    static_assert(std::is_same_v<decltype(std::get<0>(tup)), int*&>,"");
}

关于您的尝试,上面的第二个 static_assert 通过的事实解释了为什么 std::is_pointer<decltype(std::get<0>(tup))>::value 打印 false/0:那是 引用int*,而不是int*。另一方面,下面的 打印 true/1:

std::cout << std::is_pointer_v<std::remove_reference_t<decltype(std::get<0>(tup))>>;

看到我用 is_pointer_v 代替 is_pointeris_same_v 代替 is_same 了吗?带有 _v 的是辅助元函数,它们为您提供非 _v 元函数的 value 成员。 remove_reference_tremove_reference 的工作方式类似,但给出了 type 成员。

作为,您得到的类型是一个参考。 除了他的回答,我想说你可以更容易地得到元组元素的实际类型:

std::tuple_element_t<0, decltype(tup)>