Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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 with static_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 on std::get
), in this case int*&
, where int*
is the type of the element. If you use it to initialize another variable you get a copy of it (so no more reference for elem
, just int*
), just like int x = r;
defines x
to be a copy of r
regardless of r
being a reference or not.
#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*&>,"");
As regards your attempt, the fact that the second static_assert
above is passing, explains why std::is_pointer<decltype(std::get<0>(tup))>::value
prints false
/0
: that is a reference to int*
, not an int*
. On the other hand, the following does print true
/1
:
std::cout << std::is_pointer_v<std::remove_reference_t<decltype(std::get<0>(tup))>>;
See that I've used is_pointer_v
instead of is_pointer
and is_same_v
instead of is_same
? Those with _v
are helper metafunctions that give you the value
member of the non-_v
metafunctions. remove_reference_t
works similarly with respect to remove_reference
, but giving the type
member.
As Enrico explained, the type you were getting was a reference.
In addition to his answer, I'd say you can get the actual type of the element of the tuple more easily with:
std::tuple_element_t<0, decltype(tup)>
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.