I am currently learning metaprograming in C++, and I'm trying to see whether an element of a tuple is a pointer. I tried this approach:
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
I thought this was strange, so I examined the type clang deduced (I'm using clang-10), which is
__tuple_element_t<0UL, tuple<int *, int>
And it looks like some internal type.
Why do I get this weird type and what would be the proper way to get the actual type of an element of the tuple? I have only a solution which uses an intermediate auto
variable, but is hardly optimal.
std::is_same
/std::is_same_v
can be very helpful in TMP and, when looking for types being equal to other types, it's invaluable when used in conjunction withstatic_assert
.With the following code you can see that
std::get
gives you a reference to the element of the tuple (as confirmed by cppreference's page onstd::get
), in this caseint*&
, whereint*
is the type of the element. If you use it to initialize another variable you get a copy of it (so no more reference forelem
, justint*
), just likeint x = r;
definesx
to be a copy ofr
regardless ofr
being a reference or not.As regards your attempt, the fact that the second
static_assert
above is passing, explains whystd::is_pointer<decltype(std::get<0>(tup))>::value
printsfalse
/0
: that is a reference toint*
, not anint*
. On the other hand, the following does printtrue
/1
:See that I've used
is_pointer_v
instead ofis_pointer
andis_same_v
instead ofis_same
? Those with_v
are helper metafunctions that give you thevalue
member of the non-_v
metafunctions.remove_reference_t
works similarly with respect toremove_reference
, but giving thetype
member.