Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >传递多个函数并将其结果存储在一个元组中。

传递多个函数并将其结果存储在一个元组中。
EN

Stack Overflow用户
提问于 2016-03-18 07:04:51
回答 6查看 507关注 0票数 10

考虑一下这一产出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int foo (int, char) {std::cout << "foo\n";  return 0;}
double bar (bool, double, long ) {std::cout << "bar\n";  return 3.5;}
bool baz (char, short, float) {std::cout << "baz\n";  return true;}

int main() {
    const auto tuple = std::make_tuple(5, 'a', true, 3.5, 1000, 't', 2, 5.8);
    multiFunction<2,3,3> (tuple, foo, bar, baz);  // foo  bar  baz
}

因此multiFunction<2,3,3>tuple的前2个元素传递给foo,接下来的3个tuple元素传递给bar,等等.我做到了这一点(除非函数有重载,这是一个单独的问题)。但是被调用的每个函数的返回值都会丢失。我希望这些返回值存储在某个地方,比如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
std::tuple<int, double, bool> result = multiFunction<2,3,3> (tuple, foo, bar, baz);

但我不知道怎么实现。对于那些想要帮助完成这个任务的人,下面是我的(更新的)工作代码,它只将输出存储到一个字符串流中。返回所有值并不容易,特别是如果保存在流中的对象是复杂的类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <tuple>
#include <utility>
#include <sstream>

template <std::size_t N, typename Tuple>
struct TupleHead {
    static auto get (const Tuple& tuple) {  // The subtuple from the first N components of tuple.
        return std::tuple_cat (TupleHead<N-1, Tuple>::get(tuple), std::make_tuple(std::get<N-1>(tuple)));
    }
};

template <typename Tuple>
struct TupleHead<0, Tuple> {
    static auto get (const Tuple&) { return std::tuple<>{}; }
};

template <std::size_t N, typename Tuple>
struct TupleTail {
    static auto get (const Tuple& tuple) {  // The subtuple from the last N components of tuple.
        return std::tuple_cat (std::make_tuple(std::get<std::tuple_size<Tuple>::value - N>(tuple)), TupleTail<N-1, Tuple>::get(tuple));
    }
};

template <typename Tuple>
struct TupleTail<0, Tuple> {
    static auto get (const Tuple&) { return std::tuple<>{}; }
};

template <typename Tuple, typename F, std::size_t... Is>
auto functionOnTupleHelper (const Tuple& tuple, F f, const std::index_sequence<Is...>&) {
    return f(std::get<Is>(tuple)...);
}

template <typename Tuple, typename F>
auto functionOnTuple (const Tuple& tuple, F f) {
    return functionOnTupleHelper (tuple, f, std::make_index_sequence<std::tuple_size<Tuple>::value>{});
}

template <typename Tuple, typename... Functions> struct MultiFunction;

template <typename Tuple, typename F, typename... Fs>
struct MultiFunction<Tuple, F, Fs...> {
    template <std::size_t I, std::size_t... Is>
    static inline auto execute (const Tuple& tuple, std::ostringstream& oss, const std::index_sequence<I, Is...>&, F f, Fs... fs) {
        const auto headTuple = TupleHead<I, Tuple>::get(tuple);
        const auto tailTuple = TupleTail<std::tuple_size<Tuple>::value - I, Tuple>::get(tuple);
    //  functionOnTuple (headTuple, f);  // Always works, though return type is lost.
        oss << std::boolalpha << functionOnTuple (headTuple, f) << '\n';  // What about return types that are void???
        return MultiFunction<std::remove_const_t<decltype(tailTuple)>, Fs...>::execute (tailTuple, oss, std::index_sequence<Is...>{}, fs...);
    }
};

template <>
struct MultiFunction<std::tuple<>> {
    static auto execute (const std::tuple<>&, std::ostringstream& oss, std::index_sequence<>) {  // End of recursion.
        std::cout << std::boolalpha << oss.str();
        // Convert 'oss' into the desired tuple?  But how?
        return std::tuple<int, double, bool>();  // This line is just to make the test compile.
    }
};

template <std::size_t... Is, typename Tuple, typename... Fs>
auto multiFunction (const Tuple& tuple, Fs... fs) {
    std::ostringstream oss;
    return MultiFunction<Tuple, Fs...>::execute (tuple, oss, std::index_sequence<Is...>{}, fs...);
}

// Testing
template <typename T> int foo (int, char) {std::cout << "foo<T>\n";  return 0;}
double bar (bool, double, long ) {std::cout << "bar\n";  return 3.5;}
template <int...> bool baz (char, short, float) {std::cout << "baz<int...>\n";  return true;}

int main() {
    const auto tuple = std::make_tuple(5, 'a', true, 3.5, 1000, 't', 2, 5.8);
    std::tuple<int, double, bool> result = multiFunction<2,3,3> (tuple, foo<bool>, bar, baz<2,5,1>);  // foo<T>  bar  baz<int...>
}
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2016-03-18 08:12:46

这里有一种方法,可以贪婪地推导出参数的数量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <tuple>

namespace detail {
    using namespace std;
    template <size_t, size_t... Is, typename Arg>
    constexpr auto call(index_sequence<Is...>, Arg&&) {return tuple<>{};}

    template <size_t offset, size_t... Is, typename ArgT, typename... Fs>
    constexpr auto call(index_sequence<Is...>, ArgT&&, Fs&&...);

    template <size_t offset, size_t... Is,
              typename ArgT, typename F, typename... Fs,
              typename=decltype(declval<F>()(get<offset+Is>(declval<ArgT>())...))>
    constexpr auto call(index_sequence<Is...>, ArgT&& argt, F&& f, Fs&&... fs) {
        return tuple_cat(make_tuple(f(get<offset+I>(forward<ArgT>(argt))...)),
                         call<offset+sizeof...(Is)>(index_sequence<>{},
                                                    forward<ArgT>(argt),
                                                    forward<Fs>(fs)...));}

    template <size_t offset, size_t... Is, typename ArgT, typename... Fs>
    constexpr auto call(index_sequence<Is...>, ArgT&& argt, Fs&&... fs) {
        return call<offset>(index_sequence<Is..., sizeof...(Is)>{},
                            forward<ArgT>(argt), forward<Fs>(fs)...);}
}
template <typename ArgT, typename... Fs>
constexpr auto multifunction(ArgT&& argt, Fs&&... fs) {
    return detail::call<0>(std::index_sequence<>{},
                           std::forward<ArgT>(argt), std::forward<Fs>(fs)...);}

演示。但是,由于tuple_cat是递归调用的,因此返回值的数量具有二次时间复杂度。相反,我们可以使用稍微修改过的call版本来获取每个调用的索引--然后直接获得实际的tuple

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <tuple>

namespace detail {
    using namespace std;
    template <size_t, size_t... Is, typename Arg>
    constexpr auto indices(index_sequence<Is...>, Arg&&) {return tuple<>{};}

    template <size_t offset, size_t... Is, typename ArgT, typename... Fs>
    constexpr auto indices(index_sequence<Is...>, ArgT&&, Fs&&...);

    template <size_t offset, size_t... Is, typename ArgT, typename F, class... Fs,
             typename=decltype(declval<F>()(get<offset+Is>(declval<ArgT>())...))>
    constexpr auto indices(index_sequence<Is...>, ArgT&& argt, F&& f, Fs&&... fs){
        return tuple_cat(make_tuple(index_sequence<offset+Is...>{}),
                         indices<offset+sizeof...(Is)>(index_sequence<>{},
                                                       forward<ArgT>(argt),
                                                       forward<Fs>(fs)...));}

    template <size_t offset, size_t... Is, typename ArgT, typename... Fs>
    constexpr auto indices(index_sequence<Is...>, ArgT&& argt, Fs&&... fs) {
        return indices<offset>(index_sequence<Is..., sizeof...(Is)>{},
                            forward<ArgT>(argt), forward<Fs>(fs)...);}

    template <typename Arg, typename F, size_t... Is>
    constexpr auto apply(Arg&& a, F&& f, index_sequence<Is...>) {
        return f(get<Is>(a)...);}

    template <typename ITuple, typename Args, size_t... Is, typename... Fs>
    constexpr auto apply_all(Args&& args, index_sequence<Is...>, Fs&&... fs) {
        return make_tuple(apply(forward<Args>(args), forward<Fs>(fs),
                          tuple_element_t<Is, ITuple>{})...);
    }
}

template <typename ArgT, typename... Fs>
constexpr auto multifunction(ArgT&& argt, Fs&&... fs) {
    return detail::apply_all<decltype(detail::indices<0>(std::index_sequence<>{},
                                                         std::forward<ArgT>(argt),
                                                         std::forward<Fs>(fs)...))>
             (std::forward<ArgT>(argt), std::index_sequence_for<Fs...>{},
              std::forward<Fs>(fs)...);}

演示2

票数 7
EN

Stack Overflow用户

发布于 2016-03-18 08:16:35

建筑从地面向上和忽略完美的转发,使我不得不键入较少。我们需要几个助手。首先,我们需要一个应用程序的部分版本,它从我们要应用到函数的元组中获取哪些索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<class Tuple, class F, size_t... Is>
auto partial_apply(Tuple tuple, F f, std::index_sequence<Is...>) {
    return f(get<Is>(tuple)...);
}

然后,我们需要为元组的每个子集调用该函数。假设我们已经将所有函数和索引包装在一个元组中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <class Tuple, class FsTuple, class IsTuple, size_t... Is>
auto multi_apply(Tuple tuple, FsTuple fs, IsTuple indexes, std::index_sequence<Is...>) {
    return std::make_tuple(
        partial_apply(tuple,
            std::get<Is>(fs),
            std::get<Is>(indexes)
            )...
        );
}

因此,在这种情况下,我们最终想要调用multi_apply(tuple, <foo,bar,baz>, <<0,1>,<2,3,4>,<5,6,7>>, <0, 1, 2>)

我们所需要知道的就是构建indexes部件。我们从<2,3,3>开始。我们需要得到部分和(<0,2,5>),并将其添加到索引序列<<0,1>,<0,1,2>,<0,1,2>>中。所以我们可以写一个部分和函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <size_t I>
using size_t_ = std::integral_constant<size_t, I>;

template <class R, size_t N>
R partial_sum_(std::index_sequence<>, R, size_t_<N> ) {
    return R{};
}

template <size_t I, size_t... Is, size_t... Js, size_t S>
auto partial_sum_(std::index_sequence<I, Is...>,
        std::index_sequence<Js...>, size_t_<S> )
{
    return partial_sum_(std::index_sequence<Is...>{},
        std::index_sequence<Js..., S>{}, size_t_<S+I>{} );
}

template <size_t... Is>
auto partial_sum_(std::index_sequence<Is...> is)
{
    return partial_sum_(is, std::index_sequence<>{}, size_t_<0>{} );
};

我们可以用它作为一个元组生成所有索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <size_t... Is, size_t N>
auto increment(std::index_sequence<Is...>, size_t_<N> )
{
    return std::index_sequence<Is+N...>{};
}

template <class... Seqs, size_t... Ns>
auto make_all_indexes(std::index_sequence<Ns...>, Seqs... seqs)
{
    return std::make_tuple(increment(seqs, size_t_<Ns>{})...);
}

就像这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template <size_t... Is, class Tuple, class... Fs>
auto multiFunction(Tuple tuple, Fs... fs)
{
    static_assert(sizeof...(Is) == sizeof...(Fs));
    return multi_apply(tuple,
        std::make_tuple(fs...),
        make_all_indexes(
            partial_sum_(std::index_sequence<Is...>{}),
            std::make_index_sequence<Is>{}...
            ),
        std::make_index_sequence<sizeof...(Is)>{}
        );

}

如果要处理void返回,只需使partial_apply返回单个元素(或空元组)的元组,并将multi_apply中的make_tuple()用法更改为tuple_cat()

票数 4
EN

Stack Overflow用户

发布于 2016-03-18 09:37:20

这里还有另一个难题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<std::size_t N>
constexpr Array<std::size_t, N> scan(std::size_t const (&a)[N])
{
    Array<std::size_t, N> b{};
    for (int i = 0; i != N - 1; ++i)
        b[i + 1] = a[i] + b[i];
    return b;
}

template<std::size_t O, std::size_t... N, class F, class Tuple>
inline decltype(auto) eval_from(std::index_sequence<N...>, F f, Tuple&& t)
{
    return f(std::get<N + O>(std::forward<Tuple>(t))...);
}

template<std::size_t... O, std::size_t... N, class Tuple, class... F>
inline auto multi_function_impl1(std::index_sequence<O...>, std::index_sequence<N...>, Tuple&& t, F... f)
{
    return pack(eval_from<O>(std::make_index_sequence<N>(), f, std::forward<Tuple>(t))...);
}

template<std::size_t... I, std::size_t... N, class Tuple, class... F>
inline auto multi_function_impl0(std::index_sequence<I...>, std::index_sequence<N...>, Tuple&& t, F... f)
{
    constexpr std::size_t ns[] = {N...};
    constexpr auto offsets = scan(ns);
    return multi_function_impl1(std::index_sequence<offsets[I]...>(), std::index_sequence<N...>(), std::forward<Tuple>(t), f...);
}

template<std::size_t... N, class Tuple, class... F>
auto multi_function(Tuple&& t, F... f)
{
    return multi_function_impl0(std::make_index_sequence<sizeof...(N)>(), std::index_sequence<N...>(), std::forward<Tuple>(t), f...);
}

其中packArray分别类似于std::make_tuplestd::array,但是为了克服一些问题:

  • std::make_tuple破坏了它的args,因此失去了引用。
  • std::array不能用c++14中的参数写它的标记

演示

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36087785

复制
相关文章
python使用元组、字典向函数传递多个
# -*- coding: utf-8 -*- __author__ = 'River' def fun(name,age): print "%s %s" % (name,age) def fun2(name,*args,**dicargs): print "%s %s %s" % (name,args,dicargs) t=("River","15") dic={'name':'river','age':'26'} #注意这个name和这个age的key,必须和fun中的参数一致 fun("ss",":"
py3study
2020/01/08
1.3K0
在函数中接受元组与字典
# 在函数中接受元组与字典 有一种特殊方法,即分别使用 * 或 ** 作为元组或字典的前缀,来使它们作为一个参数为 函数所接收。当函数需要一个可变数量的实参时,这将非常有用。 # 代码 # 当args变量前面添加了一个*时,函数的所有其他的参数都将传递到args中,并作为一个元组储存 # 如果采用的是 ** 前缀,则额外的参数将被视为字典的键值—值配对。 def powersum(power, *args): '''Return the sum of each argument raised to
benym
2022/07/14
1.2K0
【说站】python在函数中传递实参
若要使函数接受不同类型的实参,则必须将接受任意数量实参的形参放在函数定义的最后。首先,Python匹配位置实参和关键词实参,然后将剩余的实参收集到最后一个形参中。
很酷的站长
2022/11/23
1.6K0
【说站】python在函数中传递实参
PHP在函数体中传递与接收参数
默认情况下,PHP是按值传递参数的。值传递参数调用函数时将常量或变量的值(通常称其为实参)传递给函数的参数(通常称为形参)。值传递的特点是实参与行参分别存储在内存中,是两个不相关的独立变量。因此,在函数内部改变形参的值时,实参的值一般是不会改变的。
用户7657330
2020/08/14
2.7K0
测试结果存储并使用图表展示
数据源来自于pytest执行之后的结果,由于使用allure进行结果的保存,所以直接读取对应的测试结果文件
zx钟
2022/01/18
8330
测试结果存储并使用图表展示
context.Context是做为参数传递还是存储在struct中?
在很多的API接口中,我们发现函数或方法的第一个参数往往是context.Context。Context在进程通信之间提供了取消、超时以及父子进程之间传递数据的方法。那我们在编码实践中是应该将Context存储于struct中还是以参数的方式在函数或方法直接传递呢?
Go学堂
2023/01/31
9870
jsp中在href中传递参数
<% Configuration conf = new Configuration(); URI uri = new URI("hdfs://192.168.0.52:9010"); FileSystem fileSystem = FileSystem.get(uri, conf); //System.out.println("Hdfs directory is"+"\n"); Path src1 = new Path("hdfs://192.168.0.52:9
闵开慧
2018/03/30
4.7K0
结构体数组在函数之间传递数据
明的数组,进行函数调用时,实参将数组名中存放的数组首地址传递给形参数组名。这样,实参数组名和形参名代表的是同一个结构体数组,因此在被调函数中对数组元素结构体变量的值进行修改后,回到主调函数通过实参数组名访问数组时,可以发现这个改变。
pigeon
2022/04/11
1.9K0
结构体数组在函数之间传递数据
一个函数返回多个值
第一种方法:函数返回的是一个指针地址(数组地址),这个内存地址有多个变量寄存在里面。这个方法我不太会用,传地址传值我常常搞的淅沥糊涂。
Java架构师必看
2021/03/22
1.4K0
VBA在多个文件中Find某字符的数据并复制出来
【问题】有几个文件,每个文件中有很多条记录,我现在要提取出含有“名师”两个字符的记录。
哆哆Excel
2022/10/25
2.9K0
VBA在多个文件中Find某字符的数据并复制出来
Java并发之Executor(返回结果处理)运行多个任务并处理第一个结果运行多个任务并处理所有结果
并发编程常见的问题,就是当采用多个并发任务来解决一个问题,我们往往只对第一个返回的结果有兴趣。比如,对一个数组有多种排序算法,可以并发启动所有算法,但是对于一个给定的数组,第一个得到排序结果的算法就是最快的排序算法。
desperate633
2018/08/22
1.4K0
Java并发之Executor(返回结果处理)运行多个任务并处理第一个结果运行多个任务并处理所有结果
python中多个if语句用法_python中if函数多个条件怎么用
1.只有 if 进行判断desserts = [‘ice cream’, ‘chocolate’, ‘apple crisp’, ‘cookies’]
全栈程序员站长
2022/11/09
4.4K0
[GO] 变参函数-GO中函数传递变长参数
如果函数的最后一个参数是采用 ...type 的形式,那么这个函数就可以处理一个变长的参数,这个长度可以为 0,这样的函数称为变参函数。
唯一Chat
2020/10/16
9560
[GO] 变参函数-GO中函数传递变长参数
如果函数的最后一个参数是采用 ...type 的形式,那么这个函数就可以处理一个变长的参数,这个长度可以为 0,这样的函数称为变参函数。
唯一Chat
2020/10/27
8500
捕获AOP级别的异常并将其传递到Controller层
欢迎来到本篇技术博客,今天我们将讨论如何在一个现代的Java应用中,捕获AOP(面向切面编程)级别的异常,并将这些异常传递到Controller层进行合适的处理。异常处理在构建可靠的应用程序中起着关键作用,而AOP则可以帮助我们更好地管理和组织代码。在这篇文章中,我们将深入研究如何结合AOP和异常处理来构建健壮的应用。
疯狂的KK
2023/09/27
1.1K0
捕获AOP级别的异常并将其传递到Controller层
结构体类型数据在函数之间的传递
(3)结构体变量也可以作为函数的返回值,使用 return语句从被调函数返回一个结构体变
pigeon
2022/04/11
2.1K0
结构体类型数据在函数之间的传递
如何将多个参数传递给 React 中的 onChange?
在 React 中,一些 HTML 元素,比如 input 和 textarea,具有 onChange 事件。onChange 事件是一个非常有用、非常常见的事件,用于捕获输入框中的文本变化。有时候,我们需要将多个参数同时传递给 onChange 事件处理函数,在本文中,我们将介绍如何实现这一目标。
网络技术联盟站
2023/06/07
2.7K0
【Python】元组 tuple ① ( 元组 tuple 简介 | 元组不可修改 | 元组定义 | 定义只有一个元素的元组 | 元组嵌套 )
列表 List 中的数据是可修改的 , 如果有这样一种场景 , 数据生成后 , 不能修改 , 列表就不适用了 ;
韩曙亮
2023/10/11
2240
点击加载更多

相似问题

调用函数并传递存储在元组中的参数?

34

搜索元组列表并返回多个结果

24

如何将函数结果传递给元组?

22

获得多个延迟的结果并传递给函数

11

在Rust中在元组中传递多个引用

15
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文