This may be silly question as I'm very new to C .
But I have the following body of code.
#include <iostream>
#include <vector>
#include <tuple>
int main() {
std::vector<std::tuple<int, int>> edges(4,{1,2});
for (auto i = std::begin (edges); i != std::end (edges); i) {
std::cout << std::get<0>(i) << " "<< std::get<1>(i)<< " ";
}
}
In my eyes this makes sense, I have a vector of tuples which I'm initialising. I then iterate through the vector printing each of the two elements of the tuple individually.
However the code doesn't work returning
8:26: error: no matching function for call to 'get'
std::cout << std::get<0>(i) << " "<< std::get<1>(i)<< " ";
^~~~~~~~~~~
Could someone please explain why.
Thanks in advance Ben.
CodePudding user response:
I would change to a range-based for
loop
for (auto const& edge : edges) {
std::cout << std::get<0>(edge) << " "<< std::get<1>(edge)<< " ";
}
Otherwise to access each edge, you need to dereference your iterator using *
to get the actual tuple itself
for (auto iter = std::begin(edges); iter != std::end(edges); iter) {
std::cout << std::get<0>(*iter) << " "<< std::get<1>(*iter)<< " ";
}
CodePudding user response:
i
is not a std::tuple<int, int>
, it is a pointer (iterator) to one (std::tuple<int, int>*
); you need to dereference it.
If you are able to step to C 17 you could use structured bindings in a range-based for loop instead:
for (auto [a, b] : edges) {
std::cout << a << " " << b << " ";
}
CodePudding user response:
Error message can be intimidating. Sometimes you need to dig a bit to find the relevant parts. For your code, when compiled with gcc, this part of the error message is a good hint:
In file included from <source>:3:
/opt/compiler-explorer/gcc-trunk-20211209/include/c /12.0.0/tuple:1380:5: note: candidate: 'template<long unsigned int __i, class ... _Elements> constexpr std::__tuple_element_t<__i, std::tuple<_UTypes ...> >& std::get(tuple<_UTypes ...>&)'
1380 | get(tuple<_Elements...>& __t) noexcept
| ^~~
/opt/compiler-explorer/gcc-trunk-20211209/include/c /12.0.0/tuple:1380:5: note: template argument deduction/substitution failed:
<source>:8:37: note: '__gnu_cxx::__normal_iterator<std::tuple<int, int>*, std::vector<std::tuple<int, int> > >' is not derived from 'std::tuple<_UTypes ...>'
8 | std::cout << std::get<0>(i) << " "<< std::get<1>(i)<< " ";
| ~~~~~~~~~~~^~~
The compilers internal names being used in the message don't make it easier, though what the message tries to tell is that there is some get
that takes a tuple as parameter and returns its element (constexpr std::__tuple_element_t<__i, std::tuple<_UTypes ...> >& std::get(tuple<_UTypes ...>&)
), but what you pass is an iterator from a vector of tuples (__gnu_cxx::__normal_iterator<std::tuple<int, int>*, std::vector<std::tuple<int, int> > >'
). They don't match. You need to dereference the iterator to get a reference to the tuple.