【问题标题】:How to iterate over a tuple of elemenets that have the same base class如何迭代具有相同基类的元素元组
【发布时间】:2021-09-13 10:34:33
【问题描述】:

对元组进行迭代是 C++ 世界中的一个常见问题,我知道可以完成的各种方法 - 通常使用递归和可变参数模板。
原因是元组通常包含不同的元素类型,正确处理每种类型的唯一方法是拥有与该类型匹配的特定重载。然后我们让编译器使用递归将每个元素分派给正确的函数。

我的情况是这样的:我有一个元素的元组,每个元素都是一个模板类的实例:

std::tuple<my_class<int>, my_class<string>, my_class<float>>

另外,my_class&lt;T&gt;my_class_base 的派生类,它不是模板。
考虑到这个约束,是否可以编写一个 at(tuple_type&amp; tuple, size_t n) 函数以 O(1) 步返回元组的第 n 个元素作为对基类的引用?

那我可以写了

for (size_t i = 0; i < N; i++){
   auto& o = at<my_base_class>(tuple, i);
   o.call_base_method(...);
} 

谢谢。

【问题讨论】:

标签: c++ tuples


【解决方案1】:

你可能只使用std::apply:

std::apply([](auto&...args){ (args.call_base_method(), ...); }, tuple);

要回答你的问题,你可以这样做:

template <std::size_t... Is, typename tuple_type>
my_class_base& at_impl(std::index_sequence<Is...>, tuple_type& tuple, size_t n)
{
    my_class_base* bases[] = {&std::get<Is>(tuple)...};
    *return bases[n];
}

template <typename tuple_type>
my_class_base& at(tuple_type& tuple, size_t n)
{
    auto seq = std::make_index_sequence<std::tuple_size<tuple_type>::value>();
    return at_impl(seq, tuple, n);
}

Demo

【讨论】:

  • @KonradRudolph:修正了错字并添加了演示。谢谢
  • 对于复杂性,我认为返回一次std::array&lt;reference_wrapper&lt;my_class_base&gt;, N&gt; 并对其进行迭代会更安全。
  • 很好的解决方案。 MSVC 将此函数编译为在 O(n) 中运行的程序集(用内存地址填充堆栈数组),因为 MSVC 优化充其量是幼稚的。尽管如此,我还是选择了这个解决方案,因为它非常紧凑和优雅。干得好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 2014-06-13
  • 2023-04-07
  • 1970-01-01
  • 2022-10-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多