【问题标题】:Accessing elements in a vector of tuples C++访问元组向量中的元素 C++
【发布时间】:2022-01-14 07:35:39
【问题描述】:

我有以下代码体。

#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)<< " ";
        }
}

在我看来这是有道理的,我有一个正在初始化的元组向量。然后我遍历向量,分别打印元组的两个元素中的每一个。

但是代码doesn't work返回

8:26: error: no matching function for call to 'get'
   std::cout << std::get<0>(i) << " "<< std::get<1>(i)<< " ";
                ^~~~~~~~~~~

谁能解释一下原因?

【问题讨论】:

  • i 是元组上的迭代器; *i 是一个元组。
  • 你的元组代表什么,我经常发现用清晰的名称创建我自己的结构会使代码更具可读性。我还将用基于范围的 for 循环替换 for 循环并迭代向量的 const & 。比如:for(const auto& edge : edges) std::cout
  • offtopic:元组设计用于模板。在常规代码中,最好将结构与正确命名的字段一起使用。

标签: c++ c++14


【解决方案1】:

我会改为基于范围的for 循环

for (auto const& edge : edges) {
    std::cout << std::get<0>(edge) << " "<< std::get<1>(edge)<< " ";
}

否则要访问每条边,您需要使用 * 取消引用您的迭代器以获取实际的元组本身

for (auto iter = std::begin(edges); iter != std::end(edges); ++iter) {
    std::cout << std::get<0>(*iter) << " "<< std::get<1>(*iter)<< " ";
}

【讨论】:

    【解决方案2】:

    i 不是std::tuple&lt;int, int&gt;,它是指向一个(std::tuple&lt;int, int&gt;*)的指针(迭代器);你需要取消引用它。


    如果您能够进入 C++17,则可以在基于范围的 for 循环中使用结构化绑定:

    for (auto [a, b] : edges) {
        std::cout << a << " " << b << " ";
    }
    

    【讨论】:

      【解决方案3】:

      错误信息可能令人生畏。有时您需要挖掘一下才能找到相关部分。对于你的代码,当compiled with gcc,这部分错误信息是一个很好的提示:

      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)<< " ";
            |                          ~~~~~~~~~~~^~~
      

      消息中使用的编译器内部名称并没有使它更容易,尽管消息试图告诉的是有一些 get 将元组作为参数并返回其元素 (constexpr std::__tuple_element_t&lt;__i, std::tuple&lt;_UTypes ...&gt; &gt;&amp; std::get(tuple&lt;_UTypes ...&gt;&amp;)),但是您传递的是来自元组向量的迭代器 (__gnu_cxx::__normal_iterator&lt;std::tuple&lt;int, int&gt;*, std::vector&lt;std::tuple&lt;int, int&gt; &gt; &gt;')。他们不匹配。您需要取消引用迭代器以获取对元组的引用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-28
        • 1970-01-01
        • 1970-01-01
        • 2012-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多