【问题标题】:Calling a lambda for each nth argument of multiple tuples?为多个元组的每个第 n 个参数调用一个 lambda?
【发布时间】:2020-10-22 22:35:43
【问题描述】:

我正在尝试编写一个代码,该代码使用从一组可变元组中提取的输入参数调用 lambda。但是,我的尝试没有编译:

#include <iostream>
#include <tuple>
#include <utility>
#include <type_traits>

template <typename ...>
struct first_of;

template <typename T, typename ... Args>
struct first_of<T, Args...> {
    using type = std::decay_t<T>;
};

template <typename T>
struct first_of<T> {
    using type = std::decay_t<T>;
};

template <typename ... T>
using first_of_t = typename first_of<T...>::type;

template <typename Fn, typename... Tuples, std::size_t... Idxs>
void run_impl(Fn&& fn, std::index_sequence<Idxs...>, Tuples... t) {
  auto temp = {(fn(std::get<Idxs>(t)...), true)...};
  (void)temp;
}

template <typename Fn, typename... Tuples>
void run(Fn&& fn, Tuples&&... tuples) {
  run_impl(std::forward<Fn>(fn), std::make_index_sequence<std::tuple_size<first_of_t<Tuples...>>::value>{}, std::forward<Tuples>(tuples)...);
}

int main() {
    auto a = std::make_tuple(1, 2.34, "one");
    auto b = std::make_tuple(32, 5.34, "two");

    auto print = [](auto& f, auto& g) { std::cout << f << ", " << g << std::endl; };
    run(print, a, b);
}

我期待以下输出:

1、32
2.34, 5.34
一,二

我使用的是 c++14,所以很遗憾,没有折叠表达式。 这是代码的上帝螺栓链接:https://godbolt.org/z/G19n5z

【问题讨论】:

    标签: c++ tuples c++14 variadic-templates template-meta-programming


    【解决方案1】:

    最简单的方法是添加另一个间接层,让run_impl 委托给另一个执行实际调用的函数。我冒昧地将你的函数重命名为call_transposed()

    template <std::size_t I, typename Fn, typename... Tuples>
    void call_with_nth(Fn&& fn, Tuples&&... t) {
        fn(std::get<I>(std::forward<Tuples>(t))...);
    }
    
    template <typename Fn, std::size_t... Idxs, typename... Tuples>
    void call_transposed_impl(Fn&& fn, std::index_sequence<Idxs...>, Tuples&&... t) {
      auto temp = {(call_with_nth<Idxs>(fn, std::forward<Tuples>(t)...), true)...};
      (void)temp;
    }
    
    template <typename Fn, typename... Tuples>
    void call_transposed(Fn&& fn, Tuples&&... tuples) {
      call_transposed_impl(
          std::forward<Fn>(fn),
          std::make_index_sequence<std::tuple_size<first_of_t<Tuples...>>::value>{},
          std::forward<Tuples>(tuples)...);
    }
    

    Godbolt link

    我不确定您的代码为什么不起作用,但我怀疑std::get&lt;Idxs&gt;(t)... 正在尝试同时扩展两个包Idxst,让您以后没有包可以扩展。这段代码通过一次只处理一个包来避免这个问题。

    【讨论】:

    • 谢谢,我实际上最终实现了 std::apply 之类的东西,并将参数作为元组传递,它起作用了(这也是另一个间接级别),但是您的解决方案要整洁得多。
    猜你喜欢
    • 1970-01-01
    • 2022-08-24
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2015-07-08
    • 2017-08-23
    相关资源
    最近更新 更多