C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 传递许多函数并将其所有结果存储在元组中大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
虑这个输出
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
}

因此,多功能< 2,3>采用元组的前2个元素,并将它们传递给foo,接下来的元组3个元素,并将它们传递给bar等.我得到了这个工作(除了函数有重载,这是一个单独的问题).但是,所有函数的返回值都会丢失.我希望这些返回值存储在某个地方,像

std::tuple<int,bool> result = multiFunction<2,baz);

但我不知道如何实现.对于那些想要帮助完成这些工作的人来说,这是迄今为止的(更新的)工作代码,它将输出仅存储到字符串流中.不容易得到所有的值,特别是如果保存在流中的对象是复杂的类.

#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... 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...>&,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::index_sequence<>) {  // End of recursion.
        std::cout << std::boolalpha << oss.str();
        // Convert 'oss' into the desired tuple?  But how?
        return std::tuple<int,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,fs...);
}

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

int main() {
    const auto tuple = std::make_tuple(5,5.8);
    std::tuple<int,foo<bool>,baz<2,5,1>);  // foo<T>  bar  baz<int...>
}

解决方法

这里有一种方法,其中参数的数量贪婪地推导出来:
#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,typename ArgT,typename... Fs>
    constexpr auto call(index_sequence<Is...>,ArgT&&,Fs&&...);

    template <size_t offset,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,Fs&&... fs) {
        return call<offset>(index_sequence<Is...,sizeof...(Is)>{},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)...);}

Demo.但是,由于tuple_cat是递归调用的,所以上面的返回值的数量有二次时间复杂度.相反,我们可以使用稍微修改调用本来获取每个调用的索引 – 然后直接获得实际的元组

#include <tuple>

namespace detail {
    using namespace std;
    template <size_t,typename Arg>
    constexpr auto inDices(index_sequence<Is...>,typename... Fs>
    constexpr auto inDices(index_sequence<Is...>,class... Fs,typename=decltype(declval<F>()(get<offset+Is>(declval<ArgT>())...))>
    constexpr auto inDices(index_sequence<Is...>,Fs&&... fs){
        return tuple_cat(make_tuple(index_sequence<offset+Is...>{}),inDices<offset+sizeof...(Is)>(index_sequence<>{},Fs&&... fs) {
        return inDices<offset>(index_sequence<Is...,forWARD<Fs>(fs)...);}

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

    template <typename ITuple,typename Args,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,Fs&&... fs) {
    return detail::apply_all<decltype(detail::inDices<0>(std::index_sequence<>{},std::forWARD<Fs>(fs)...))>
             (std::forWARD<ArgT>(argt),std::index_sequence_for<Fs...>{},std::forWARD<Fs>(fs)...);}

Demo 2.

大佬总结

以上是大佬教程为你收集整理的c – 传递许多函数并将其所有结果存储在元组中全部内容,希望文章能够帮你解决c – 传递许多函数并将其所有结果存储在元组中所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。