遍历 C++ std::tuple 的通用方法

问题描述 投票:0回答:1

我的目标是有一种通用的方法来遍历

std::tupple
,下面的代码试图展示它:

#include <iostream>
#include <tuple>

using namespace std;
template <typename t, size_t t_idx, typename t_tuple>
concept visit_tuple_element_value = requires(t &&p_t, const t_tuple &p_tuple) {
  {
    p_t.template operator()<t_idx>(
        std::declval<std::add_const_t<std::add_lvalue_reference_t<t_tuple>>>())
    } -> std::same_as<bool>;
};

template <typename t_tuple, typename t_function, size_t t_idx = 0>
requires(visit_tuple_element_value<t_function, t_idx, t_tuple>)

    void traverse_tuple_values(t_function p_function, const t_tuple &p_tuple) {
  if constexpr (t_idx < std::tuple_size_v<t_tuple>) {
    if (p_function.template operator()<t_idx>(p_tuple)) {
      traverse_tuple_values<t_tuple, t_function, t_idx + 1>(p_function,
                                                            p_tuple);
    }
  }
}

struct a {};
struct b {};
struct c {};

using my_tuple = std::tuple<b, a, c>;

int main() {

  my_tuple _tuple;

  auto _visitor = [&]<size_t t_idx>(const my_tuple & /*p_tuple*/) {
    if constexpr (std::is_same_v<std::tuple_element_t<t_idx, my_tuple>, a>) {
      std::cout << "'a' is at index " << t_idx << std::endl;

    } else {
      std::cout << "'a' is NOT at index " << t_idx << std::endl;
    }
    return true;
  };

  traverse_tuple_values(_visitor, _tuple);
  return 0;
}

我收到错误:

'traverse_tuple_values<std::tuple<b, a, c>, (lambda at main.cpp:63:19), 3UL>' 

我不明白为什么

p_function.template operator()<t_idx>(p_tuple)
,因此
_visitor
,被称为
t_idx
等于3,如果我在
traverse_tuple_values
if constexpr (t_idx < std::tuple_size_v<t_tuple>)

g++ --version
报告
g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

c++ template-meta-programming c++-concepts
1个回答
0
投票

正确的代码是,感谢@Eljay:

template <typename t_tuple, typename t_function, size_t t_idx = 0>
requires(visit_tuple_element_value<t_function, t_idx, t_tuple>)

    void traverse_tuple_values(t_function p_function, const t_tuple &p_tuple) {
  if constexpr (t_idx < std::tuple_size_v<t_tuple>) {
    if (p_function.template operator()<t_idx>(p_tuple)) {
      if constexpr ((t_idx + 1) < std::tuple_size_v<t_tuple>) {
        traverse_tuple_values<t_tuple, t_function, t_idx + 1>(p_function,
                                                              p_tuple);
      }
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.