我的目标是有一种通用的方法来遍历
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
正确的代码是,感谢@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);
}
}
}
}