Home > Back-end >  Accessing elements in a vector of tuples C
Accessing elements in a vector of tuples C

Time:12-09

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.

  • Related